06 CSI模块指南
上一节介绍了 OV5640 的处理流程。流程中的参数由寄存器控制,STM32H7 再通过接口配置这些寄存器。
这些底层细节已经封装在 OpenMV 固件的 csi 模块中。和入门课的 HelloWorld 一样,导入模块、创建实例后,就可以调用相应函数。
1. 传感器调节项
基础配置已经在 HelloWord和IDE工具介绍 中介绍。这里再看 PPT 中列出的几个调节项:
csi0.hmirror(True) # 左右翻转
csi0.vflip(True) # 上下翻转
csi0.auto_exposure(False, exposure_us=8000) # 曝光
csi0.auto_gain(True, gain_db_ceiling=16) # 增益
csi0.auto_whitebal(False, rgb_gain_db=(0.0, 0.0, 0.0)) # 白平衡
csi0.framerate(15) # 帧率上限
这些语句使用前面已经创建的 csi0 对象,按需要放在初始化部分。参数含义可以在本站 csi 模块库 中搜索。
曝光
OpenMV 默认开启自动曝光、自动增益和自动白平衡。
曝光控制像素收集光信号的时间。曝光时间越长,积累的光生电荷通常越多,图像也越明亮。
但它不是越长越好:光照充足时,曝光过长会使像素接近饱和,导致图像过曝。上面的 exposure_us=8000 使用微秒作为单位。
增益
增益可以把采集到的信号放大。在光线较暗,又不适合继续延长曝光时,可以通过增益提高画面亮度。
增益也不是越大越好,因为信号放大的同时,噪声也会被放大。
白平衡
白平衡通过调整 RGB 三个通道,校正不同光源造成的颜色偏差。例如白炽灯的光偏暖黄,而冷白 LED 的光偏蓝。
人眼会适应不同光源,自动白平衡也在做类似的调整。但它会改变图像中的 RGB 数值,因此进行色块追踪等与颜色有关的任务时,通常要在画面稳定后关闭自动白平衡。
2. snapshot 如何获取图像
img = csi0.snapshot() 返回一个 image.Image 对象,后续图像处理大多围绕它进行。
OV5640 配置完成后会持续输出图像数据。采图时,STM32H7 的 DCMI 接收数据,DMA 把数据搬运到 SDRAM 缓冲区。
按图中的过程来看:
- DCMI 等待帧起始信号。
- 开始接收这一帧的数据,并触发 DMA 搬运。
- 一帧数据传输完成,产生完成通知。
snapshot()返回对应的图像对象。
这个对象关联着图像缓冲区中的数据。可以借助 C 语言结构体的概念理解:对象里保存了图像相关信息,像素数据则位于对应的内存中。
3. 单缓冲、双缓冲与多缓冲
单缓冲
只有一块缓冲区时,采集和处理需要轮流使用它。CPU 等待图像采集完成,再处理这一帧;处理结束后,缓冲区才能交给下一次采集。
双缓冲
双缓冲允许 CPU 处理一块缓冲区时,DMA 向另一块缓冲区采图。
如果 CPU 还没处理完,而另一块缓冲区已经采满,就可能发生丢帧。CPU 再取图时,也可能需要等待当前采集完成。因此双缓冲的实际效果仍取决于采集时间和处理时间。
多缓冲与预览
多块缓冲区可以排成队列,让图像采集与 CPU 处理衔接起来。默认的自动清理会在丢帧时清理排队的旧帧,使后续 snapshot() 尽量取得较新的画面。
图中的队列是示意图。具体缓冲数量通过 framebuffers() 配置;单缓冲、双缓冲、三缓冲与更多缓冲的 FIFO 模式,见 csi 模块库。
程序开始下一次采图时,上一帧处理后的图像可更新到单独的预览缓冲区,再经 USB 传到 IDE。预览用的缓冲区和采图用的缓冲区并不是同一块。
后续进入图像处理模块,主要通过具体项目学习它的用法。