本队伍编号CICC3042,本文重点介绍蜂鸟处理器和OV5640模块的结合方式、OV5640的窗口调节,以及图像的resize方法,试图以一种简单快速的方式得到令人满意的OV5640的输出图像,为进一步的图像处理做准备。
我们首先实现了摄像头采集模块和HDMI显示模块,随后将二者与蜂鸟结合,结合方式如下所示,虚线框中为我们添加的部分,同时对蜂鸟原来的外设进行裁剪,仅保留需要的部分。这里OV5640和HDMI模块成为蜂鸟的外设,可以由处理器控制启动,并进行少量配置。同时为了降低开发难度,二者的很多配置是固定的,通过verilog硬件模块初始化,不受处理器控制,这样的优点是初始化速度快、降低了软硬件开发难度;缺点是缺少配置灵活性,不能在运行时修改配置,但是在一个工程中摄像头的配置经常是固定的,因此缺点带来的损失并不大。
摄像头模块和HDMI模块的具体结构如下,OV5640的寄存器配置保存在查找表中,Reg Config模块上电后自动将寄存器配置通过I2C接口发送给摄像头;Frame Capture提供摄像头的时钟驱动,并接收其采集的RGB数据,写到FIFO中,FIFO实现两个不同时钟模块的数据通信;我们实现了通过AXI接口直接访问DDR的DMA模块,包括读写两个通道,摄像头采集的数据通过写通道写入DDR,而HDMI显示模块通过读通道将DDR的数据显示到屏幕上;LCD Driver根据显示分辨率生成HDMI或VGA时序驱动;HDMI Out模块为Digilent提供的IP,其输出引脚直接接到HDMI接口上;Controller模块提供系统工作的状态机,控制两个模块的运行。
接下来介绍OV5640摄像头模块,可以参考OV5640 datasheet,这里推荐CrazyBingo提供的教程 http://crazyfpga.com/ 。
在实际工程中,我们可能需要调节输出窗口大小,OV5640 datasheet中给出了设置采样窗口大小的寄存器,如下图所示。进行窗口设置的寄存器为0x3800-0x3813。
由下图得知0x3808、0x3809和0x380A、0x380B决定了最终输出的窗口大小,一般情况下我们只需要改动这四个寄存器的值即可调节输出窗口。
上述调节窗口的方法用于简单调节,其本质上是在采样的原图基础上直接裁剪,仅得到了原图的一部分,因此显示器输出也是原图的一部分。有时我们希望显示器的显示范围更大或者更加灵活,可以将摄像头采集的图像经过resize后保存,两种方法的区别如下图所示:
这时为了方便地实现resize,可以利用Vivado HLS,具体为hls_video.h中的hls::Resize函数或hls::Resize_opr_linear函数,数据端口综合为axi-stream接口,顶层函数代码如下:
void
resize(hls::stream
#pragma HLS INTERFACE axis port=in
#pragma HLS INTERFACE axis port=out
#pragma HLS dataflow
hls::Mat
hls::Mat
stream_to_mat(in, raw_img);
// hls::Resize(raw_img, resize_img, HLS_INTER_LINEAR);
hls::Resize_opr_linear(raw_img, resize_img);
mat_to_stream(resize_img, out);
}
生成的模块如下:
将其连接到Frame Capture和Write FIFO之间即可,这种连接方式在摄像头采集数据的同时进行处理,因为摄像头的帧率有限,resize模块的处理时间足够,所以不会影响性能。实际测试发现采集的图像具有较好的视野范围,并且可以随意修改输出图片大小。