4.18. 多个传感器¶
少数几款 OpenMV Cam 在同一块开发板上配置了两个图像传感器 —— 最常见的是一个彩色摄像头搭配一个 FLIR® Lepton® 热成像传感器,但同样的模式也适用于彩色加事件传感器的开发板,以及任何未来的双传感器硬件。每个传感器都有自己的像素阵列、自己的控制总线,并以各自的帧率运行各自的流水线。CSI API 通过让应用程序为每个物理传感器实例化一个 CSI 对象,扩展到对它们的支持。
4.18.1. 选择使用哪个传感器¶
CSI 构造函数接受一个 cid 参数,用于指定开发板上的某个特定传感器。cid=-1(默认值)选择 主 传感器;命名的 cid 常量则按芯片 ID 选择某个次级传感器:
import csi
csi_rgb = csi.CSI() # primary colour sensor
csi_thermal = csi.CSI(cid=csi.LEPTON) # FLIR® Lepton®
每个实例都拥有自己的配置 —— 像素格式、framesize、曝光/增益旋钮、帧缓冲区池 —— 并且独立于其他实例进行复位、配置和读取。受支持的次级传感器所对应的常量(LEPTON、GENX320,以及 CSI 参考文档中列出的其他常量)指定了应用程序期望在次级端口上看到的芯片;如果实际芯片不匹配,驱动程序将使构造失败。
4.18.2. 从两个传感器同时采集¶
每个传感器都独立于另一个运行其采集流水线 —— 彩色传感器可能每秒提供三十帧,而 Lepton® 只提供九帧。处理这种不匹配的直接方式,是让 较快 的传感器驱动循环,并以非阻塞方式读取较慢的传感器,取走任何已就绪的内容,在没有内容时跳过本次迭代:
import csi
csi_rgb = csi.CSI()
csi_thermal = csi.CSI(cid=csi.LEPTON)
csi_rgb.reset() # powers the rail, pulses RESET
csi_rgb.pixformat(csi.RGB565)
csi_rgb.framesize(csi.QVGA)
csi_thermal.reset(hard=False) # I2C reconfigure only
csi_thermal.pixformat(csi.GRAYSCALE)
csi_thermal.framesize(csi.QQVGA)
while True:
rgb_img = csi_rgb.snapshot() # blocks for next colour frame
thermal_img = csi_thermal.snapshot(blocking=False) # returns None if not ready
if thermal_img is not None:
# process aligned colour + thermal pair
pass
else:
# process colour only on this iteration
pass
阻塞式的 snapshot() 为循环定速;非阻塞式的那个在自上次调用以来有新帧到达时返回最近的一帧热成像帧,否则返回 None。应用程序持续以彩色传感器的帧率运行,并在 Lepton® 每产生一帧时获取一帧热成像帧。
相反的模式 —— 两次背靠背的阻塞式快照 —— 也是可行的,但此时循环会以两个传感器中 较慢 的那个的速率运行,较快传感器的流水线在迭代之间被迫停顿。请根据应用程序的下游处理实际想要驱动的速率来选择。
4.18.4. 选择流的来源¶
拥有两个传感器的摄像头有两个 CSI 实例,但它们之间仍只有一个流帧缓冲区。一个构造函数参数用于选择由哪个传感器的帧来馈送预览:
csi_rgb = csi.CSI() # primary
csi_thermal = csi.CSI(cid=csi.LEPTON,
stream=True) # preview source
stream=True 使命名的实例成为来源。在没有 stream= 参数时,主传感器(cid=-1,默认值)即为来源;用次级传感器的 cid= 构建的实例除非显式传入 stream=True,否则在预览上保持沉默。对未被选中的传感器调用 snapshot() 仍会照常将帧采集到该传感器的帧缓冲区中 —— 只是不会更新预览。