一、先看效果
话不多说,先上视频看效果。
基于FPGA:运动目标检测
二、硬件选择
开发板Altera:EP4CE10F17C8
摄像头:OV5640
缓存数据:SDRAM
板子是自己制作的
三、目标追踪帧差法原理
根据帧差法的实现流程,设计的双端口SDRAM控制器,一侧读写端口用做帧缓存,另一个端口用来缓存视频流,如图所示。
在使用SDRAM双端口时,只要合理控制好读写地址,即可实现SDRAM两个读写端口独立运行。其中,SDRAM1端口用来作为帧缓存,SDRAM2端口用来测试算法的效果。
首先,摄像头的输出格式是RGB565格式,经过颜色空间的转换转化为灰度数据流,写入到SDRAM1端口侧,等到延时一帧时刻到来,从第二帧开始两帧图像做差分。
但此时得到的差分后的二值图像,由于光照背景的变化会有很大的噪声,因此还需要进行了形态学滤波。然后求得包围盒左上角和右下角像素坐标,与原始RGB图像叠加后重新写入到SDRAM2端口,此时VGA就可以显示处理后的图像的效果。
四、rgb2yuv灰度化处理(可参考正点原子说明书)
从公式中(1)可以看到:由于FPGA不善于处理浮点数;这里完成了浮点数向定点数的转换;各个系数均扩大256倍,最后在计算完之后除以256,如公式(2)。
Y = 0.299 R + 0.587 G + 0.114 B
U = - 0.1687 R - 0.3313 G + 0.5 B + 128 (1)
V = 0.5 R - 0.4187 G - 0.0813 B + 128
Y=(77*R+150*G+29*B)»8;
U =(-43R-85G+128B+128*256)»8 (2)
V=(128R-107G-21B+128*256)»8
在Verlog里面,使用组合逻辑不能直接按上述公式(2)在计算,不然组合逻辑延时太大,导致时序不收敛,这里就需要添加寄存器来切割流水线;利用FPGA 并行处理的特点加速计算。这里分三级流水线处理:第一级流水线计算所有乘法; 第二级流水线计算所有加法,把正的和负的分开进行加法;第三级流水线计算最终的和,若为负数取0。输入到输岀有三个clock的时延仿真波形如下图所示:
五、差分处理模块
差分处理模块主要含有gary_shfit和 Diff_frame两个模块,对应图1的延时一帧和差分处理方框;摄像头数据一路数据写入sdram写口1侧,做为帧缓存,另一路是当前的图像数据,通过场信号控制延时从sdram 读口1侧读数据,这样,如下所示,sdr_rd为sdram读信号。
//延时读sdram控制
reg rd_en;
always@ (posedge clk or negedge resetb) begin
if ( !resetb)
rd_en <-#ck2q o;
else if(~ivsync & ivsync_do)
rd _en <-#ck2q l'bl;
end
assign sdr_rd = rd_en & clken;
assign sdr_nwr -rd_en ;
然后可完成两帧图像数据data_next - data_cur 差分。大于设定阈值threshold为 15 则认为时目标区域,设置为255;注意阈值可以根据需要调节控制。
//差分处理
reg[7:0]data_diff;
wire [7:0]data;
assign data=(data_next>data_cur) ?((data_next-data_cur > threshold)? 8'd255 :8'd0):( (data_next==data_our)? 8'd0:((data_cur-data_next 5 threshold) ? 8'd255 :8 'd0));
如下图所示,可以看到 data_next - data_cur = 8’d130时,大于设定阈值15则输出数据post_img_Bit为255。
六、腐蚀和膨胀形态学滤波
由于侦查法受环境影响,处理之后会有噪声,由于是二值图像,这里采用形态学滤波,先进行腐蚀处理就是去除小边界和孤立点﹔再进行膨胀处理,填充空洞。
本次采用33窗口实现腐蚀和膨胀操作,如图1.6及1.7所示:
如下图所示,得到的是matrix_p11~matrix_p339个像素数据组成3x3图像模板,这里通过行缓存设计(缓存了2行图像数据),延时时两行数据后,在如下黄线后第3行,得到完整的3x3图像模板。部分代码如下所示。
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
{matrix_p11, matrix_p12, matrix_p13} <= 3'b0;
{matrix_p21, matrix_p22, matrix_p23} <= 3'b0;
{matrix_p31, matrix_p32, matrix_p33} <= 3'b0;
end
else if(read_frame_href)
begin
if(read_frame_clken) //Shift_RAM data read clock enable
begin
{matrix_p11, matrix_p12, matrix_p13} <= {matrix_p12, matrix_p13, row1_data}; //1th shift input
{matrix_p21, matrix_p22, matrix_p23} <= {matrix_p22, matrix_p23, row2_data}; //2th shift input
{matrix_p31, matrix_p32, matrix_p33} <= {matrix_p32, matrix_p33, row3_data}; //3th shift input
end
else
begin
{matrix_p11, matrix_p12, matrix_p13} <= {matrix_p11, matrix_p12, matrix_p13};
{matrix_p21, matrix_p22, matrix_p23} <= {matrix_p21, matrix_p22, matrix_p23};
{matrix_p31, matrix_p32, matrix_p33} <= {matrix_p31, matrix_p32, matrix_p33};
end
end
腐蚀膨胀仿真波形图:
七、包围盒处理
包围盒处理如上图的 boundary 灰度帧差法的得到二值图像,然后设计包围盒得到上下左右4点像素坐标,框出目标区域。
通过行场信号,设计行列计数器,从而可以获取图像每个像素点的坐标信息,然后设计4个寄存器分别是edg_up 、 edg_down、edg_left、edg_right目标的上下左右四个点,实时与行列计数器比较,也就是求最大值( edg_down和edg_right)和最小值(edg_up和edg_left),代码如下所示:文章来源:https://www.toymoban.com/news/detail-443542.html
always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
edg_up <= 10'd479;
edg_down <= 10'd0;
edg_left <= 10'd639;
edg_right <= 10'd0;
end
else if(vsync_rising) begin
edg_up <= 10'd479;
edg_down <= 10'd0;
edg_left <= 10'd639;
edg_right <= 10'd0;
end
else if(per_frame_clken & per_frame_href)begin
if(per_img_Y == 1'b1) begin
if(edg_up > v_cnt)
edg_up <=v_cnt ;
else
edg_up <=edg_up ;
if(edg_down < v_cnt)
edg_down <=v_cnt ;
else
edg_down <=edg_down ;
if(edg_left > h_cnt)
edg_left <= h_cnt ;
else
edg_left <=edg_left ;
if(edg_right < h_cnt)
edg_right <=h_cnt ;
else
edg_right <=edg_right ;
end
end
end
八、板子原理图及源码工程获取
①:直接点链接获取:基于FPGA的运动目标检测(硬件+原理图+源码+仿真+设计文档)
②:私信我或者添加微信获取(完整原理图、硬件、源码工程、技术指导)文章来源地址https://www.toymoban.com/news/detail-443542.html
到了这里,关于基于FPGA:运动目标检测(VGA显示,原理图+源码+硬件选择)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!