UVC 相机硬件同步(UVC Camera Hardware Synchronization)是指一台符合 UVC 的 USB 相机,能否通过同步引脚、触发脉冲或厂商扩展,让一台或多台相机在受控曝光时刻采集图像。
结论要分两层:标准 UVC 接口本身通常只保证视频流枚举、格式协商和常规控制;真正的曝光级 硬件同步 取决于具体相机是否额外提供 外部触发、sync in/out、GPIO、FSIN、strobe 或厂商 SDK/Extension Unit。
从 UVC 数据接收侧看,主机不能在帧已经经由 USB 到达之后,再把多路相机“变成硬同步”。接收侧能做的是稳定收帧、记录主机时间戳、解析设备时间戳、做 软件同步 和误差评估;曝光时刻是否同步,必须由相机模组的硬件、固件和传感器时序先保证。
核心问题
多相机、机器人和高速运动场景关心的不是“主机什么时候收到帧”,而是“每台相机的传感器什么时候开始曝光”。如果两台相机曝光时刻相差几毫秒,静态场景可能看不出来,但手眼标定、双目深度、视觉伺服 和数据采集会把这个时间差转成空间误差。
需要区分三种能力:
| 能力 | 对齐对象 | 能否由普通 UVC 保证 |
|---|---|---|
| 同时打开视频流 | 采集进程启动时间 | 不能严格保证 |
| 软件同步 | 主机收到帧的时间戳 | 可以做,但有抖动 |
| 硬件同步 | 传感器曝光起点或帧起点 | 需要相机硬件/固件支持 |
核心对象
| 对象 | 含义 | 对同步的影响 |
|---|---|---|
| USB host | 运行采集程序的主机 | 只能看到枚举、控制和到达时间,通常看不到真实曝光起点 |
| UVC device | 按 UVC 协议暴露的视频设备 | 负责格式协商、控制请求和视频数据传输 |
| image sensor | CMOS/CCD 传感器 | 决定曝光窗口、读出方式和是否支持触发模式 |
| frame start | 一帧曝光或读出的起点 | 硬同步真正要约束的时刻 |
| sync signal / shared clock | 同步脉冲、共享时钟或 PPS 一类电气时序源 | 直接约束多台相机的曝光或帧起点 |
| control channel | I2C、SPI、MCU 内部接口、厂商 SDK 或 UVC Extension Unit 等配置路径 | 用来切换模式和设置参数,但它本身不等于同步信号 |
| GPIO / FSIN | 相机上的同步输入脚 | 接收外部触发脉冲,让帧起点由外部信号决定 |
| strobe / sync out | 相机输出的曝光或帧同步信号 | 可驱动光源、其他相机或记录真实曝光时刻 |
| UVC Extension Unit | 厂商自定义控制通道 | 可用于打开触发模式或读取扩展状态,但语义不属于通用 UVC 标准 |
核心机制
普通 UVC 采集链路通常是:
- 主机枚举 USB 设备,发现 VideoControl 和 VideoStreaming 接口。
- 应用选择分辨率、像素格式和帧率,驱动与设备协商流参数。
- 相机传感器按自身时钟连续曝光、读出、进入相机缓存。
- UVC 固件把图像封装成 USB 传输包,发给主机。
- 驱动或应用给帧打接收时间戳。
这条链路没有给“外部触发某一帧曝光”提供统一、跨厂商的标准语义。UVC 可以有标准控制,也可以有 Extension Unit,但 Extension Unit 的含义由厂商固件定义;同样叫 UVC 的两台相机,其触发寄存器、GPIO 电平、触发模式和失败行为都可能不同。
真正的多相机硬同步链路通常是另一条路径:
- 通过控制通道配置相机进入同步模式,例如 master/slave、外触发、固定曝光、固定帧率和时间戳计数方式。
- 由同步源输出共享时钟或触发脉冲,脉冲到达各相机的同步输入脚。
- 每个 sensor 或相机固件把曝光起点锁定到这个电气事件,而不是锁定到主机发起
STREAMON的时间。 - 图像随后仍然可以通过 UVC 上传;UVC 负责传输已经采集好的帧,不负责让这些帧同时曝光。
- 如果设备提供
dev_ts、frame counter 或 strobe 记录,主机可以用它验证同步质量;如果只有主机接收时间戳,就只能评估接收链路,不足以证明曝光同步。
时间上可以写成:
t_host = t_exp_start + T_exp_ref + T_readout + T_camera_pipe + T_usb + T_driver_queue其中:
t_exp_start是传感器开始曝光的时间,硬件同步真正要约束它。T_exp_ref是从曝光起点到代表性图像时刻的偏移,常取曝光中心exposure_time / 2。T_readout是传感器读出时间;卷帘快门 下不同行有不同读出和曝光时刻。T_camera_pipe是 ISP、压缩、缓存等相机内部流水线延迟。T_usb是 USB 传输延迟,受带宽、端点类型、Hub 和主机调度影响。T_driver_queue是驱动、内核缓冲和应用队列延迟。
软件同步 只能拿 t_host 做对齐;硬件同步 要让多台相机满足:
abs(t_exp_start_i - t_exp_start_j) < epsilonepsilon 是允许的曝光时间误差,例如机器人高速运动时可能要求亚毫秒级。只靠 UVC 收帧时间戳无法证明这个不等式成立,因为中间的 USB、缓存和驱动延迟不是常数。
控制总线和同步信号要分开理解:控制总线回答“相机是否进入触发模式、曝光时间是多少、帧率是多少”,同步信号回答“这一帧到底在什么时候开始曝光”。USB/UVC 主机侧逐个发送开始采集命令,最多只能让软件流程接近同时启动;Linux 用户态调度、驱动队列、USB microframe 调度、Hub 仲裁和设备固件缓冲都会引入不可控偏差。
因此,对 UVC 接收侧系统来说,合理职责边界是:
- 接收、缓存、编码或落盘多路 UVC 数据。
- 记录
t_host、单调时钟、帧序号和丢帧信息。 - 解析厂商提供的设备时间戳、frame counter 或 metadata。
- 做后处理对齐、漂移拟合、同步误差统计。
- 用闪光、LED 同步靶或 strobe 回读实测
epsilon。
不合理的职责期待是:只靠主机端同时打开多个 /dev/video*、同时调用 VIDIOC_STREAMON 或事后重写时间戳,就承诺 6 路相机已经曝光级硬同步。
判断流程
| 观察到的规格 | 判断 |
|---|---|
| 只写 UVC、免驱、USB webcam | 大概率不支持真正硬同步 |
| 有 GPIO / FSIN / trigger input / sync input | 可能支持,需要确认电平、边沿、模式和 SDK |
| 有 strobe / flash / exposure output | 可以输出曝光事件,但不一定能被外部触发 |
| 有 vendor Extension Unit / SDK trigger mode | 可能通过 UVC 扩展开启触发,但不可假设跨平台通用 |
| 有 全局快门 | 有利于同步采集,但不等于有触发同步 |
| 只有相同帧率和相同 USB Hub | 不能说明曝光同步 |
实际选型时要问四个问题:
- 是否有物理同步引脚,还是只有软件命令?
- 触发的是单张 still capture、视频流下一帧,还是每个 frame start?
- 触发模式下是否仍能预览、调曝光、稳定输出目标帧率?
- 厂商是否给出触发电平、最小脉宽、最大频率、曝光时间约束和同步误差?
- 控制通道只是配置同步模式,还是同时有独立的同步输入/输出电气路径?
- 多相机共享的是同一个物理时钟/触发源,还是只有各自时间戳可以在主机侧换算?
工程用途
- 双目或多目相机:减少左右图之间的运动时间差。
- 机器人数据采集:让图像、关节状态、力传感器和控制周期有可解释的时间关系。
- 高速运动检测:避免多相机视角之间出现不同瞬间的目标姿态。
- 主动光源:用 strobe 信号让照明只在曝光窗口打开。
边界与常见坑
- UVC 免驱不等于支持硬同步;它只是说明主机能用标准类驱动读取视频流。
- 全局快门 不等于硬同步;全局快门解决同一帧内部各像素是否同时曝光,硬同步解决不同设备之间何时曝光。
- “支持硬件 still capture”不一定等于“支持连续视频帧触发”;有些相机只支持按引脚拍一张静态图。
- 主机端同时调用
VideoCapture.open()或同时启动线程,只是软件并发,不是曝光同步。 - 主机端同时
STREAMON不是硬同步;它没有绕过操作系统调度、USB 调度和设备内部缓冲。 - 设备时间戳可比不等于曝光同时发生;它可以支持后处理对齐,但还要确认时间戳代表曝光起点、曝光中心、读出完成还是打包发送时刻。
- 控制总线不等于同步线;没有共享触发或共享时钟时,配置命令只能设置模式,不能给每一帧提供确定的物理起点。
- USB 带宽不足会造成丢帧、缓冲增长和时间戳漂移;即使曝光同步,主机收到帧的时间也可能不齐。
- 触发频率不能只看目标 FPS,还要满足曝光时间、读出时间、相机处理时间和 USB 吞吐限制。