犀牛派 X1 接入 ZED 2i 双目相机实战:V4L2 高清采集、性能测试与掉帧分析

犀牛派 X1 接入 ZED 2i 双目相机实战:V4L2 高清采集、性能测试与掉帧分析

1. 项目背景:为什么要对一台 USB 双目相机做这么多测试?

项目面向钢结构表面腐蚀巡检,后续希望利用双目相机同时提供高清 RGB 图像与空间深度信息,再将腐蚀分割结果定位到钢结构的具体位置。硬件采用阿加犀犀牛派 X1 开发板与 Stereolabs ZED 2i 双目相机,Ubuntu 主机承担程序开发、对照测试及算法研究。

刚拿到硬件时,一个看似简单的目标——“把相机接上开发板,拍下两张清楚的图像”——就涉及若干不同层次的验证:USB 是否正确枚举?Android 是否能调用该摄像头?Linux 内核是否暴露 UVC 视频节点?视频格式能否设置?能否取得完整帧?取得一张高清图后,能否以目标 FPS 持续采集?

我们最终选择 ADB + Android NDK + Linux V4L2,先解决原始视频采集,再做连续取帧与主机对照实验。这样能够把系统接口、采集代码和性能问题逐层拆开,而不是一开始就把采集、深度估计、腐蚀识别都混在一起。

img

图1|本项目实际使用的犀牛派 X1 开发板与 ZED 2i 双目相机。

img

图2|Ubuntu 主机、X1 开发板及 ZED 2i 的实验连接关系。

2. 环境、测试对象与指标口径

2.1 实际软硬件配置

项目当前实验配置
边缘计算设备阿加犀犀牛派 X1
开发板系统Android 13,API 33,ARM64 / aarch64
内核Linux 5.15.178(测试时)
视频相机Stereolabs ZED 2i 双目相机
开发及对照主机Ubuntu 22.04,x86_64
设备管理ADB
交叉编译Android NDK r30,aarch64-linux-android33-clang
视频采集接口Linux UVC / V4L2
相机输出格式YUYV(双目左右水平拼接)
保存格式转换为 RGB 后写入 PPM 文件
USB 枚举速度X1 和 Ubuntu 侧均记录约 5000M(USB 3 链路枚举信息)

本次使用的是同一台 ZED 2i 和同一条连接线。在 X1 与 Ubuntu 两端,用对应平台编译的 V4L2 基准程序执行相同采集模式的对照测试。两端 USB Host 控制器、内核驱动与调度环境并不相同,因此结果可用于比较平台表现,但不能直接当作底层原因的定论。

2.2 四种需要分开的“成功”

(1)USB 识别成功:lsusb 看到了摄像头;(2)视频采集成功:可以从 /dev/videoX 获取完整视频帧;(3)连续采集达到设定 FPS:有效帧数量与实际耗时满足目标;(4)端到端视觉算法稳定运行:采集、图像处理、模型推理和输出的整体时延满足业务需求。

本项目目前完成的是前面三个层次中的识别、单帧采集和对连续采集的性能测试。没有把 Ubuntu 主机上的腐蚀分割、SGBM 深度计算成果表述成已经在 X1 完成实时部署。

3. 设备接入:USB 能认出相机,为什么不等于可以取图?

3.1 通过 ADB 检查开发板

在 Ubuntu 终端运行:

adb devices

状态显示为 device 后,再查询 X1 本机的 USB 枚举:

adb shell lsusb

本次记录中,ZED 2i 对应的 USB 标识为 2b03:f880、2b03:f881。其中 2b03:f880 对应主要视频设备,另一个为相机相关接口。设备能被枚举,证明 USB 层已经看见外设;但是 Android Camera Framework 并不一定会把它注册成普通相机。

img

图3|开发板 ADB 状态与 ZED 2i USB 枚举结果。

3.2 搜索实际的视频节点

不能默认 USB 摄像头就是 /dev/video0。X1 自身也有系统相机管理节点,因此使用下面的命令按名称识别:

adb shell 'for f in /sys/class/video4linux/video*/name; do echo -n "$f : "; cat "$f"; done'

实验中显示:video0 为 cam-req-mgr,video1 为 cam_sync,video2 与 video3 均为 ZED 2i: ZED 2i。经测试,主要可用的采集节点为 **/dev/video2**。其他节点不能简单按名字相同就认为采集功能也相同。

img

图4|X1 系统识别到的 V4L2 节点。/dev/video2 为本次经验证的主视频采集节点。

3.3 Android Camera HAL 与 V4L2 的关系

本次环境下,相机虽然能通过 UVC 驱动形成 Linux 视频节点,但不能按照常规 Android 相机应用的使用方式直接取得 ZED 2i 图像。因此我们绕开普通 Camera Framework,直接对 /dev/video2 使用 V4L2 的 open、ioctl、mmap 和队列操作。这是针对当前固件与设备组合的方案,并不意味着所有 Android 设备都无法使用 USB 摄像头。

4. 自行编译 V4L2 采集程序:真正获取双目数据

4.1 为什么使用 Android NDK?

板端 Android 环境没有预装完整的 v4l2-ctl、FFmpeg、GStreamer 等调试工具,普通 x86_64 Linux 可执行文件也不能直接在 ARM64 Android 上运行。我们于是编写 C 语言采集程序,在 Ubuntu 上通过 NDK r30 交叉编译,随后用 ADB 上传到 X1。

img

图5|USB 枚举、V4L2 缓冲区采集到双目图像保存的程序流程。

程序调用的核心 V4L2 操作包括:VIDIOC_QUERYCAP(能力查询)、VIDIOC_S_FMT(设置视频格式)、VIDIOC_REQBUFS(申请缓冲区)、VIDIOC_QBUF(缓冲区排队)、VIDIOC_STREAMON(启动)、VIDIOC_DQBUF(取出视频帧)与 VIDIOC_STREAMOFF(关闭)。

如果已将环境变量 ANDROID_NDK_HOME 指向安装好的 Android NDK 根目录,可以使用下列编译形式(具体工具链路径需要与本机一致):

"$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang" \
  -O2 -Wall -Wextra zed_hd2k_capture.c -o zed_hd2k_capture

上传可执行文件并赋予权限:

adb push zed_hd2k_capture /data/local/tmp/
adb shell chmod +x /data/local/tmp/zed_hd2k_capture

提示: zed_hd2k_capture 是本项目编写的 C 语言程序,不是 Android 默认命令,也不是 ZED SDK。素材包中附有本次采集程序源码,便于理解采集流程;不同系统上复现仍需要检查 NDK 和设备权限。

4.2 ZED 2i 的 YUYV 双目拼接格式

在当前采集接口下,每个视频帧同时包含左右两个摄像头的画面,以水平拼接形式输出。因此,不能把 4416×1242 看作单眼分辨率。

视频帧(双目拼接)每路图像尺寸每帧 YUYV 理论大小
1344×376672×3761,010,688 B
2560×7201280×7203,686,400 B
3840×10801920×10808,294,400 B
4416×12422208×124210,969,344 B

img

图6|不同采集模式的左右目拼接关系。

YUYV 是一种 YUV 4:2:2 打包格式,理论平均每个像素约占 2 字节。所以一帧原始数据量为:

FrameBytes = Width × Height × 2

例如 HD2K 拼接帧:4416 × 1242 × 2 = 10,969,344 bytes。日志里 bytesperline = 8832,与 4416 × 2 对应。

4.3 HD2K 实际采集与预热

在确认视频节点、程序可执行后运行:

adb shell /data/local/tmp/zed_hd2k_capture /dev/video2

本次设置为 4416×1242 YUYV、目标 15 FPS,程序会等待 20 个完整有效帧作为预热,再将最后取得的双目图像转换为 RGB 并分成两路图像。采集程序并非通过 ZED SDK 直接获取彩色深度数据。

img

图7|实际运行 HD2K 采集程序的终端日志;取得完整有效帧,左右目 PPM 保存成功。

终端最后显示:

Stable HD2K frame acquired: 10969344 bytes
Saved:
 Left : /data/local/tmp/zed_left_hd2k.ppm
 Right: /data/local/tmp/zed_right_hd2k.ppm
Capture and HD2K stereo split successful.

将文件传回 Ubuntu 查看:

mkdir -p ~/下载/zed_v4l2_test
adb pull /data/local/tmp/zed_left_hd2k.ppm ~/下载/zed_v4l2_test/
adb pull /data/local/tmp/zed_right_hd2k.ppm ~/下载/zed_v4l2_test/

img

图8|同一次采集的左右目图像,每路原始像素尺寸均为 2208×1242。

左右目画面均能呈现同一场景,存在合理的视角差异。这里证明的是图像拆分成功,不是深度测量精度已经得到验证。

5. 首轮调试中遇到的几个问题

5.1 “设备出现了”却不能从相机应用获取画面

应分开检查 USB 枚举、视频节点、Camera HAL 与 V4L2 采集能力。USB 设备 ID 已出现,不代表 Android Camera Framework 已完成注册;节点存在,也不代表该节点一定能稳定输出需要的格式。

5.2 刚启动时可能出现绿屏、空帧或残缺帧

早期采集中出现过颜色异常,以及 bytesused=0 的情况。后来程序增加了有效字节数检查、完整帧长度检查和预热阶段;这样能够降低错误帧被当成最终图片保存的风险。

需要注意: 20 帧是本次测试采用的预热数量,不是所有相机的通用标准;简单丢弃前20帧也不能解释或修复所有曝光、白平衡与 USB 传输问题。

5.3 单帧成功不意味着视频流性能达标

上一节的日志显示 Driver frame rate: 15.000 FPS,但这是驱动报告的设定/协商帧率,不是连续取帧过程中独立计时得到的有效 FPS。这一点直接引出了下一轮测试。

6. 六种采集模式的连续帧率实测

6.1 如何定义“实测 FPS”?

基准程序设置指定的分辨率与帧率,在视频流启动后连续取帧,用实测时长与成功取得的有效帧数计算:

Measured FPS = 完成取帧的有效帧数 / 经过时间(秒)

这种 FPS 与 VIDIOC_G_PARM 等 API 报告的配置值不是一个概念。我们还会检查 sequence 的连续性,避免只看计数就忽略中间帧是否跳跃。

下表为先前保留的项目实验记录;暂未为每组模式附上完整的多轮重复测试方差,因此属于阶段性单组测试结果汇总,不是产品规格书或所有场景可保证的性能。

双目拼接模式请求 FPSX1 有效采集 FPS达标比例
1344×37610097.6797.7%
2560×7203027.9893.3%
2560×7206049.0981.8%
3840×10801510.9272.8%
3840×10803022.8076.0%
4416×1242158.2054.7%

img

图9|X1 在六种 YUYV 采集模式下的请求帧率与实际有效帧率。

可以看出,低分辨率下更容易接近目标值:例如 1344×376@100 实测约 97.67 FPS;而 HD2K 4416×1242@15 连续采集约 8.20 FPS。这里的“较低 FPS”不能直接理解为该相机在任何 X1 软件环境下都只有这一性能。

7. 与 Ubuntu 主机对照:相机、线缆有没有问题?

为了排除“相机本身无法产生目标帧率”这一简单解释,使用同一台相机和同一条线缆,在 Ubuntu 主机上进行了三种相同采集模式的测试。

拼接图像模式目标 FPSX1 实测 FPSUbuntu 实测 FPS
2560×720@606049.0960.00
3840×1080@303022.8029.73
4416×1242@15158.2015.00

img

图10|同一 ZED 2i、同一线缆,在 X1 与 Ubuntu 主机上运行对应模式的实测帧率。

Ubuntu 在这三项测试里均接近目标帧率,而 X1 在当前软件/硬件链路下出现不同程度下降。因此,排查重点应转向两个平台的采集链路差异:USB Host 控制器、驱动、缓存机制、用户态程序运行环境及系统负载等。

但是: 对照实验只能提高相关怀疑的合理性,不能直接证明某个模块“出了故障”;因为控制器、内核和调度条件尚未完全统一。

8. HD2K 的 sequence 为何从 0 跳到了 63?

在图7的高清采集日志里,程序记录的20个完整有效预热帧 sequence 依次为:

0, 1, 2, 7, 8, 9, 10, 15, 18, 19,
20, 23, 26, 27, 32, 43, 50, 53, 54, 63

img

图11|由实际采集日志绘制的 sequence 记录,虚线是假定每次取帧都连续递增的参考线。

如果按从0到63的编号范围观察,共有64个序列号位置,而我们这次只记录了20个完整有效帧,另外44个编号没有出现在这个有效帧列表中。应谨慎理解:这不等于已经证明 USB 总线上丢了44个帧或44个数据包。应用端过滤不完整帧、内核缓冲队列溢出或调度导致取帧不及时等,都可能造成类似现象。

排查时至少要把几个量分开:设备实际产生了多少帧、内核驱动接收到多少帧、DQBUF 返回多少帧、应用主动忽略了多少帧,以及最终落盘多少帧。仅凭一张截图,还不能定位到具体一层。

同理,序列跳跃的截图用于展示“存在异常”,不能代替独立连续采集的 FPS 统计。本文 HD2K 的 8.20 FPS 来自此前的连续采集基准结果,而不是从这20个帧编号直接换算。

9. 为什么不能把掉帧简单归咎于“USB 带宽不够”?

YUYV 原始吞吐量可以按拼接帧宽高、每像素2字节、设定 FPS 计算:

理论数据率(MiB/s)= Width × Height × 2 × RequestedFPS / 1,048,576
视频模式设定 FPS理论原始数据率
2560×72060210.94 MiB/s
3840×108030237.30 MiB/s
4416×124215156.92 MiB/s

img

图12|根据 YUYV 原始数据尺寸与目标帧率计算的理论数据率,不代表 USB 总线实测吞吐量。

有一个重要但容易忽略的事实:HD2K@15 的理论原始数据率,比 1080p@30 更低。但是在 X1 上,相对设定 FPS 的下降却更明显。

这表明不能简单用“分辨率越高 → 带宽越大 → 肯定掉帧”来解释。我们需要同时考虑:单帧有效载荷与缓冲区管理、USB 等时传输调度、URB 的队列深度、UVC 数据重组、DMA/内存搬运,以及处理线程是否及时执行 DQBUF 等可能因素。

此前调试中出现过与 xhci_hcd、URB 取消等相关的信息,但这些日志有的发生在关闭视频流时。当前证据只能把它们列为排查线索,不能将其直接认定为根因。 USB 协商显示约 5000M,也只能说明连接枚举速度,不等于无额外开销的有效应用数据带宽。

10. 接下来如何做更严谨的掉帧定位?

下一轮应把“观察到的异常”和“可能的解释”分开,减少重复盲测。

img

图13|针对本项目的分层排障路线(建议方案,不是已经完成的诊断结果)。

建议保留固定的测试记录字段:采集模式、UVC 格式、缓冲区个数、运行时长、成功 DQBUF 次数、过滤帧数、每帧 bytesused 与 sequence、系统负载、采集程序是否执行 RGB 转换或文件写入等。对每个模式至少重复多次,记录均值与波动区间。

在程序侧,先让基准测试只负责取帧和计时,再逐步打开颜色转换、左右目分离、保存文件,才能判断应用处理开销占了多少;在内核侧,进一步分析 UVC 队列和 xHCI / URB 相关统计,但需要有权限且避免把正常关闭视频流时的日志误判为故障。

特别说明:本文附带的是HD2K 单帧采集程序的源码。用于连续帧率统计的多模式基准程序不是这份源码本身,读者不能直接执行该单帧程序并据此复现上表所有连续 FPS 数字。

11. 工程选择:实时巡检与高清取证不必使用同一模式

对于钢结构腐蚀巡检,低分辨率实时观察与高清静态记录的需求不同。综合当前测试,可以考虑采用两个采集阶段:巡检时采用 2560×720@30 等相对稳定的模式,在 X1 上实际采集约 27.98 FPS;发现疑似腐蚀后切换 HD2K 获取静态图像,每路保留 2208×1242 的细节。

img

图14|分阶段采集与腐蚀识别的工程架构设想,尚未完成 X1 端端到端部署及性能验证。

这种“移动巡检 + 高清取证”的方案有利于把采集压力与图像细节需求进行折中,但只是后续系统设计方向。当前腐蚀模型训练、数据集测试和双目深度算法主要在 Ubuntu 主机上进行,不能据此宣称 X1 已完成全流程实时腐蚀识别与三维定位。

12. 复查命令、注意事项与实验总结

复查设备状态可依次执行:

adb devices
adb shell lsusb
adb shell 'for f in /sys/class/video4linux/video*/name; do echo -n "$f : "; cat "$f"; done'

在确认 /dev/video2 是当前实际可用节点、且板端二进制程序存在后,再执行:

adb shell 'ls -lh /data/local/tmp/zed_hd2k_capture'
adb shell /data/local/tmp/zed_hd2k_capture /dev/video2

重要: 程序会重新写入相同名称的 PPM 文件,复测前先备份已有图片;设备节点编号也可能在重连后变化。不要直接照搬 15.000 FPS 的日志输出作为连续实时性能,必须独立计时。

至此,本项目已经完成一条可复核的低层采集路径:ADB 识别设备 → UVC/V4L2 访问 → NDK 编译 → YUYV 双目取帧 → 预热与完整性检查 → RGB 拆分 → PPM 导出;同时通过连续采集和 Ubuntu 对照,发现了当前 X1 组合的部分高清模式存在掉帧与序列编号跳跃。

...全文
34 回复 打赏 收藏 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

7,903

社区成员

发帖
与我相关
我的任务
社区描述
本论坛以AI、IoT、PC 、XR、Auto等核心板块组成,为开发者提供便捷及高效的学习和交流平台。 高通开发者专区主页:https://qualcomm.csdn.net/
物联网人工智能开源 企业社区 北京·东城区
社区管理员
  • csdnsqst0050
  • chipseeker
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧