基于FPGA的图像增强和运动目标检测
一帧图像结束时,sink_eop持续一个时钟的高电平,此时sink_valid为高代表数据有效,sink_ready为高代表下一个时钟可以接收视频流数据。统计模块对统计RAM的q进行了一个时钟的延迟操作以写回统计RAM,这就意味着读统计RAM的写相比于读存在2个时钟的延迟(RAM自身就存在1个时钟的延迟,详见统计RAM的设置),统计模块设计的关键之处在于,需要判断前两个时钟内是否出现了写且写地址和
在夜间或光照较弱的场景,识别运动目标将变得困难。本设计针对以上问题,先采用直方图均衡算法对弱光图像进行增强,再用帧差法检测运动目标。
(可私信联系有偿获取全套硬件实物、Verilog源码、设计文档。)
开发环境
硬件使用小马哥FPGA生产的DMK FPGA开发板,FPGA芯片型号为EP4CE10F17C8,软件使用Quartusii18.1开发环境。
硬件开发平台介绍
本系统使用小马哥DMK FPGA开发板平台,该平台使用Altera公司的Cyclone 4系列现场可编程门阵列EP4CE10F17C8作为主控器,这个主控器包含10080个LE、414Kbits Block RAM、2个PLL和46个硬件乘法器。DMK开发板具备OV5640插针接口,可以外接OV5640摄像头模组,板载一片64Mits容量的SDRAM,并自带分辨率480x320的TFTLCD显示屏,可以实时、便捷地观察图像处理效果。板载5个按键,可以用于算法开关控制,方便对比算法效果。
FPGA系统设计
顶层设计
如图所示是FPGA设计的顶层框图,摄像头采集模块配置OV5640摄像头模组、并将OV5640输出的DVP接口视频转换成Avalon-ST视频流接口。RGB转灰度模块将彩色的视频流转换成亮度视频流,灰度化的目的方便图像增强模块和运动目标检测模块进行算法处理。图像增强模块将低照度图像进行对比度增强,运动目标检测模块则对运动目标进行检测并使用包围盒标记出来。液晶屏驱动模块用于配置液晶屏并产生液晶屏显示需要的时序信号。
图像采集模块
模块框图
如图所示,是图像采集模块的框图,顶层模块名为cmos_top,包含6个自模块:cmos2dcfifo模块、cmos_dcfifo模块、burst_read模块、cmos_scfifo模块、cmos_fifo2st模块、cmos_encode模块。
子模块功能
cmos2dcfifo模块的作用是根据DVP接口的行场同步信号提取出有效数据,并将有效数据写入到异步fifo中。
cmos_dcfifo模块是一个采用官方IP实现的8位数据输入、16位数据输出的异步fifo,其输入时钟和输入位宽都是读写相异的。写时钟采用摄像头的数据同步时钟,读时钟则采用算法处理的主时钟,一般由Qsys决定。
burst_read模块用于从异步fifo即cmos_dcfifo中突发读出一段数据并写入到同步fifo即coms_scfifo中去。
cmos_scfifo模块是采用官方IP实现的同步fifo,其作用主要是缓存数据,同时便于cmos_fifo2st模块获取图像数据和实现ready latency为1的RAW ST数据流。
cmos_fifo2st模块的作用是从cmos_scfifo中读出数据,并根据参数化的分辨率信息产生符合Avalon-ST裸流协议的视频流。
cmos_encode模块的作用是将Avalon-ST裸流视频转换成标准的Avaslon-ST视频流。
RGB转灰度模块
灰度化算法可以将彩色图像转换成灰度图像,灰度化后的图像只包含亮度信息,这使得后续的图像处理和分析变得更加简单和高效。例如,在目标跟踪、图像分割和特征提取等任务中,灰度图像的处理速度通常比彩色图像要快得多。
本设计使用加权法公式对图像进行灰度化,其公式如下:
Gray = 0.2989 * G + 0.5870 * R + 0.1140 * B
时序仿真
如图1所示,是rgb2gray模块的输入和输出时序一帧开始的波形图,其中sink组信号对应输入视频流、source组信号对应输出视频流。一帧图像开始时,sink_sop持续一个时钟的高电平,此时sink_valid为高代表数据有效,sink_ready为高代表下一个时钟可以接收视频流数据。source_sop信号延迟sink_sop信号8个时钟,该延迟是由于灰度化计算消耗了8级流水线,所以输入和输出数据之间存在8个时钟的延迟。
图1
如图2所示,是rgb2gray模块的输入和输出时序一帧结束的波形图,其中sink组信号对应输入视频流、source组信号对应输出视频流。一帧图像结束时,sink_eop持续一个时钟的高电平,此时sink_valid为高代表数据有效,sink_ready为高代表下一个时钟可以接收视频流数据。source_eop信号延迟sink_eop信号多个时钟,和source_sop延迟sink_sop信号8个时钟不同,这里的延迟是由于灰度化模块内部存在FIFO缓存数据,后级模块在某些时刻频繁拉低过source_ready,所以灰度化后的结果缓存了多个数据在FIFO中,导致source_eop延迟了sink_eop多个时钟才出来。
图2
灰度化仿真
灰度化计算公式是Y = (R*306 + G*601 + B*117)/1024,如图3所示,是rgb2gray模块的灰度化计算波形图,以输入的彩色RGB888像素值为24’h77a3bf为例,R的值为8’h77(8’d119)、G的值为8’ha3(8’d163)、B的值为8’hbf(8’d191),代入公式计算得到的结果是Y=(119*306+163*601+191*117)/1024=153,换算成十六进制Y=8’h99,可以从仿真波形中看到,8个时钟后输出的数据正是8’h99,说明设计符合要求,仿真结果正确。
图3
图像增强模块
图像增强模块是对灰度图像进行灰度直方图均衡,以达到对弱光图像进行增强的效果。
算法原理
如下所示是直方图均衡化的算法公式:
模块框图
如图4所示是灰度直方图均衡算法模块框图:
图4
子模块设计
统计模块(vip_hist_equ_count)
统计模块对统计RAM的q进行了一个时钟的延迟操作以写回统计RAM,这就意味着读统计RAM的写相比于读存在2个时钟的延迟(RAM自身就存在1个时钟的延迟,详见统计RAM的设置),统计模块设计的关键之处在于,需要判断前两个时钟内是否出现了写且写地址和当前时钟的q对应的读地址相同,若出现了则意味着当前的q不可靠,不能使用当前的q加1再写回。那么什么数据才是可靠的呢,答案是最近那个出现写地址和当前时钟的q对应的读地址相同的时钟的写数据。
统计RAM读写仲裁模块(vip_hist_equ_ram_bus_arbit)
仲裁由哪个模块可以读写统计RAM,在统计阶段由统计模块获得RAM读写权,在累积阶段则由累积模块获得RAM读写权。
累积模块(vip_hist_equ_add)
累积模块既需要负责直方图统计值的累积操作,又需要负责统计RAM的清空。
状态切换模块(vip_hist_equ_fsm)
直方图均衡化算法模块的状态机,主要是切换统计状态和累积状态,累积状态下强制拉低sink_ready。
重映射模块(vip_hist_equ_remap)
根据累积RAM中的累积数据,对输入的图像数据进行灰度重映射。
模块仿真
直方图累计仿真
首先,从整体上看一下,如图5中可看出,累计阶段发生再一帧结束以后也就是sink_sop到来以后,static_done_w代表统计完成,cumulate_done_w代表累计完成。这里我们顺便看一下统计RAM读出来的值,由于测试数据每行数据都是等于行号的,即第一行全为0,第479行全为479。所以0~223这214个灰度重复了一遍,因此统计值是1280,其余的统计值是640,因此这里也可以说明统计结果的正确性。
图5
接下来我们从局部看一下累计的波形,下图是累计阶段清空统计RAM的波形图。可以看出,写RAM始终发生在读RAM的下一个时钟,也就是边读出统计值边清空统计RAM。
图6
最后我们看一下累计的结果仿真,可以看出,灰度值0的累计结果是1280,灰度1的累计结果是2560=1280*2,因为从统计的结果得知前面0~223个灰度值的统计值都是1280,因此累计值也是等差数列递增的,每次递增1280,因此累计的结果也是正确的。
图7
直方图均衡整体仿真图
我们再看一下灰度直方图均衡算法的整体仿,以下是视频刚开始阶段的仿真波形:
图8
下图是视频中间部分的仿真波形:
图9
下图是视频结尾部分的仿真波形:
图10
帧差法运动目标检测模块
根据帧差法的实现流程,设计的双端口SDRAM控制器,一侧读写端口用做帧缓存,另一个端口用来缓存视频流,如图11所示。
图11
在使用SDRAM双端口时,只要合理控制好读写地址,即可实现SDRAM两个读写端口独立运行。其中,SDRAM1端口用来作为帧缓存,SDRAM2端口用来测试算法的效果。
首先,摄像头的输出格式是RGB565格式,经过颜色空间的转换转化为灰度数据流,写入到SDRAM1端口侧,等到延时一帧时刻到来,从第二帧开始两帧图像做差分。
但此时得到的差分后的二值图像,由于光照背景的变化会有很大的噪声,因此还需要进行了形态学滤波。然后求得包围盒左上角和右下角像素坐标,与原始RGB图像叠加后重新写入到SDRAM2端口,此时VGA就可以显示处理后的图像的效果。
模块仿真
差分处理模块仿真
差分处理模块主要含有gary_shfit 和Diff_frame两个模块,对应图1.1的延时一帧和差分处理方框;摄像头数据一路数据写入sdram 写口1侧,做为帧缓存,另一路是当前的图像数据,通过场信号控制延时从sdram 读口1侧读数据,这样,如下图12所示,sdr_rd为sdram读信号。
图12
然后可完成两帧图像数据data_next - data_cur 差分。大于设定阈值threshold为 15 则认为时目标区域,设置为255;注意阈值可以根据需要调节控制。
图13
如下图14所示,可以看到data_next - data_cur = 8’d130 时,大于设定阈值15则输出数据post_img_Bit 为255。
图14
腐蚀和膨胀形态学滤波仿真
由于帧差法受环境影响,处理之后会有噪声,由于是二值图像,这里采用形态学滤波,先进行腐蚀处理就是去除小边界和孤立点;再进行膨胀处理,填充空洞。
本次采用3x3窗口实现腐蚀和膨胀操作,如图15和16所示:
图15
图16
如下图所示,得到的是matrix_p11~matrix_p33 9个像素数据组成3x3 图像模板,这里通过行缓存设计(缓存了2行图像数据),延时时两行数据后,在如下黄线后第3行,得到完整的3x3 图像模板。部分代码如下图17所示。
图17
图18
包围盒算法模块
包围盒处理如上图的boundary 灰度帧差法的得到二值图像,然后设计包围盒得到上下左右 4点像素坐标,框出目标区域。
通过行场信号,设计行列计数器,从而可以获取图像每个像素点的坐标信息,然后设计4个寄存器分别是edg_up 、edg_down、edg_left、edg_right 目标的上下左右四个点,实时与行列计数器比较,也就是求最大值(edg_down和edg_right)和最小值(edg_up和edg_left),代码如下图19所示:
图19
为了直观看到跟踪效果,这段代码就是显示目标区域方框以及看彩色图像叠加显示图像的。
图20
如下图21包围盒仿真波形图,edg_up_d1 、edg_down_d1、edg_left_d1、edg_right_d1 四个坐标分别为277 、325、398、445 每帧结束后更新。
图21
SDRAM控制器模块仿真
如图22所示,循环写入256个数:0x0000-0x0101-0x0202-...-0xffff,同时循环读出相同地址的数据,可以看出循环读出的数据和写入的数据比对一致,说明仿真结果正确。
图22
ILI9488 TFTLCD液晶模块
简介
TFTLCD都需要驱动芯片才能够正常显示,本设计采用的TFTLCD的驱动芯片型号为ILI9488。ILI9488分辨率480*320,支持SPI、RGB、MCU等接口,DMK FPGA开发板上的电路设计只采用固定的MCU接口,并且是16bits的MCU接口。因此,驱动TFTLCD显示实际上是驱动ILI9488正常工作。
ILI9488驱动的实现
方案概述
驱动ILI9488芯片的本质,是通过MCU接口往ILI9488的显存中写入需要显示的图像,ILI9488会自动把显存中的图像数据“刷”到LCD屏幕上。没错,ILI9488这个芯片内部自带显存,也即片上RAM。但是在此之前,我们得先配置好ILI9488内部的一些寄存器值才行。所以通常驱动ILI9488分为两大步骤:初始化配置和写数据进显存。
初始化配置
ILI9488的初始化配置本质上就是配置其内部的一些寄存器,就像我们通过I2C接口初始化配置OV7725一样,ILI9488的配置我们需要通过MCU接口也就是intel 8080接口。
为了方便程序的理解,把上图中用到的信号名“翻译”成了程序中使用的接口名称。CS的作用是“Chip Select”片选,可以理解为使能,低电平有效。注意原名称中最后的那个“X”,带“X”的信号都是低电平有效的,下面不赘述。RS代表读写的是数据还是指令,高电平代表数据,低电平代表指令。WR是写使能,RD是读使能,实际上8080接口的读写信号特性更接近时钟的特性,比如数据的写入发生在WR的上升沿,就是说必须遇到WR的上升沿,数据才能被写入,光有WR为低电平这个条件还不够。这就会发生一个有趣的现象,在驱动显示过程中,WR就像时钟一样,不停地高低变化。
更多推荐
所有评论(0)