FPGA目标跟踪基于FPGA的帧差法和SAD匹配算法的目标跟踪实现
Posted fpga和matlab
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FPGA目标跟踪基于FPGA的帧差法和SAD匹配算法的目标跟踪实现相关的知识,希望对你有一定的参考价值。
1.软件版本
quartusii12.1
2.系统FPGA实现
FPGA整体的算法流程如下图所示:
FPGA的模块主要包括如下几大模块:
摄像机驱动程序,SDRAM控制程序,显示屏驱动程序,中值滤波程序,帧差法模块,SAD模板匹配模块,跟踪定位模块等等。
跟踪模块顶层程序 帧差法模块 SAD模板匹配模块,R通道 SAD模板匹配模块,G通道 SAD模板匹配模块,B通道 显示定位跟踪效果 中值滤波,R通道 中值滤波,G通道 中值滤波,B通道 跟踪模块 开发板LED控制模块 系统复位模块 摄像机视频图像捕获模块 摄像机采集数据转换为RGB像素的模块 开发板数码管模块 SDAM核 SDRAM控制器 I2C配置,主要用来配置相机的初始化状态。
|
1.帧差法模块
这个部分,就是将当前一帧图像,延迟一帧,然后相减,就可以得到。这个也是传统的差分,但是这种方法误差极大。主要包括:
目标跟踪中,基础的差分法,存在较大的缺陷,比如目标静止状态,那么就无法检测,如果场景中,运动的物体非常多,那么就会出现检测混乱的情况,如果摄像机存在较为剧烈的抖动,同样会导致检测失败。然后我们考虑到在实际中,各种跟踪目标具有一定的特殊性。因此,针对各种不同的应用场景,设置不同的模板,结合传统的帧差法,从而提升系统的性能。
帧差,其FPGA成像如下所示:
2.SAD模板匹配模块,RGB通道
这个部分的代码如下所示:
这个模块里面,我们选择的窗口大小为20*20,即在进行模板匹配的时候,选择20*20区域内的像素进行求和运算。
这个模块的实现过程是延迟,相加实现。
相当于公式:
3.显示定位跟踪效果
将差分,和模板匹配得到后的图像用一个轮廓进行表示。具体可以看仿真录像。
4.中值滤波,RGB通道
这个将图像中3*3区域内的图像的像素值,取其中间值来实现,具体可以参考中值滤波的相关原理。
5.跟踪模块
这个是根据差分帧,进行二值判决,得到大概的运动区域。
6.开发板LED控制模块
开发板硬件的配置,不涉及具体的算法原理
7.系统复位模块
开发板硬件的配置,不涉及具体的算法原理
8.摄像机视频图像捕获模块
这个部分,提供了摄像机的具体型号的datasheet,可以参考下。
9.摄像机采集数据转换为RGB像素的模块
将摄像机采集到的数据,进行拆分,然后组成RGB形式输出。
10.开发板数码管模块
开发板硬件的配置,不涉及具体的算法原理
11.SDAM核
这个部分是调用PLL核,产生控制SDRAM的时钟信号。
12.SDRAM控制器
SDRAM控制器,开发板硬件的配置,不涉及具体的算法原理
13.I2C配置,主要用来配置相机的初始化状态
I2C总线配置。开发板硬件的配置,不涉及具体的算法原理
整个系统的资源占用情况如下所示:
整个系统的RTL结构如下所示:
3.核心程序
//reset signals
Reset_Delay u2 ( .iCLK(CLOCK2_50),
.iRST(KEY[0]),
.oRST_0(DLY_RST_0),
.oRST_1(DLY_RST_1),
.oRST_2(DLY_RST_2),
.oRST_3(DLY_RST_3), //auto-start start point
.oRST_4(DLY_RST_4) //auto-start end point
);
//cmos sensor capture
CCD_Capture u3 ( .oDATA(mCCD_DATA),
.oDVAL(mCCD_DVAL),
.oX_Cont(X_Cont),
.oY_Cont(Y_Cont),
.oFrame_Cont(Frame_Cont),
.iDATA(rCCD_DATA),
.iFVAL(rCCD_FVAL),
.iLVAL(rCCD_LVAL),
.iSTART((!KEY[3])| auto_start),
.iEND(!KEY[2]),
.iCLK(~CAMERA_PIXCLK),
.iRST(DLY_RST_2)
);
//raw data to RGB conversion
wire [11:0] sCCD_R_;
wire [11:0] sCCD_G_;
wire [11:0] sCCD_B_;
RAW2RGB u4 ( .iCLK(CAMERA_PIXCLK),
.iRST_n(DLY_RST_1),
.iData(mCCD_DATA),
.iDval(mCCD_DVAL),
.oRed(sCCD_R_),
.oGreen(sCCD_G_),
.oBlue(sCCD_B_),
.oDval(sCCD_DVAL),
.iMIRROR(SW[17]),
.iX_Cont(X_Cont),
.iY_Cont(Y_Cont)
);
//图像的中值滤波
//图像的中值滤波
//图像的中值滤波
wire [11:0] sCCD_R0;
wire [11:0] sCCD_G0;
wire [11:0] sCCD_B0;
filter media_tops_u1(
.i_clk (CAMERA_PIXCLK),
.i_rst (~DLY_RST_1),
.i_din (sCCD_R_),
.o_address (),
.o_enable0 (),//NC
.o_median (sCCD_R0),
.o_enable1 (),//NC
.o_frame_flag (),
.o_Write_Address(),
.o_Write_CLK ()
);
filter media_tops_u2(
.i_clk (CAMERA_PIXCLK),
.i_rst (~DLY_RST_1),
.i_din (sCCD_G_),
.o_address (),
.o_enable0 (),//NC
.o_median (sCCD_G0),
.o_enable1 (),//NC
.o_frame_flag (),
.o_Write_Address(),
.o_Write_CLK ()
);
filter media_tops_u3(
.i_clk (CAMERA_PIXCLK),
.i_rst (~DLY_RST_1),
.i_din (sCCD_B_),
.o_address (),
.o_enable0 (),//NC
.o_median (sCCD_B0),
.o_enable1 (),//NC
.o_frame_flag (),
.o_Write_Address(),
.o_Write_CLK ()
);
//彩色图,转换为灰度图,Y = 0.3R + 0.59G + 0.11B
//彩色图,转换为灰度图,Y = 0.3R + 0.59G + 0.11B
//彩色图,转换为灰度图,Y = 0.3R + 0.59G + 0.11B
//0.3 = 1/4+1/32+1/64+1/512+1/1024
//0.59 = 1/2+1/16+1/64+1/128+1/256
//0.11 = 1/16+1/32+1/64
wire[11:0]R1;
wire[11:0]G1;
wire[11:0]B1;
wire[11:0]GRAY;
//0.3 = 1/4+1/32+1/64+1/512+1/1024
assign R1 = sCCD_R0[11],sCCD_R0[11],sCCD_R0[11:2] + sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11:5] +
sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11:6] +
sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11:9] +
sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11:10];
//0.59 = 1/2+1/16+1/64+1/128+1/256
assign G1 = sCCD_G0[11],sCCD_G0[11:1] + sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11:4] +
sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11:6] +
sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11:7] +
sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11:8];
//0.11 = 1/16+1/32+1/64
assign B1 = sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11:4] +
sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_G0[11:5] +
sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11:6];
assign GRAY = R1+G1+B1;
//获得前后2帧,进行差分计算
//获得前后2帧,进行差分计算
//获得前后2帧,进行差分计算
wire[11:0]Frame1;
wire[11:0]Frame2;
Delay_frame Delay_frame_u(
.i_clk (CAMERA_PIXCLK),
.i_rst (~DLY_RST_1),
.i_din (GRAY),
.o_frame1(Frame1),
.o_frame2(Frame2)
);
//差分
wire signed[11:0]Framediff;
assign Framediff = Frame1-Frame2;
wire signed[11:0]o_tracker;
tracker tracker_u(
.i_clk (CAMERA_PIXCLK),
.i_rst (~DLY_RST_1),
.i_data (Framediff),
.o_tracker (o_tracker)
);
//基于SAD的模板匹配
//基于SAD的模板匹配
//基于SAD的模板匹配
wire[23:0]SADR;
SAD_tops1 SAD_tops1_u1(
.i_clk (CAMERA_PIXCLK),
.i_rst (~DLY_RST_1),
.i_en (1'b1),
.i_images (sCCD_R0),
.i_images_en (1'b1),
.o_SAD (SADR),
.o_en ()
);
wire[23:0]SADG;
SAD_tops1 SAD_tops1_u2(
.i_clk (CAMERA_PIXCLK),
.i_rst (~DLY_RST_1),
.i_en (1'b1),
.i_images (sCCD_G0),
.i_images_en (1'b1),
.o_SAD (SADG),
.o_en ()
);
wire[23:0]SADB;
SAD_tops1 SAD_tops1_u3(
.i_clk (CAMERA_PIXCLK),
.i_rst (~DLY_RST_1),
.i_en (1'b1),
.i_images (sCCD_B0),
.i_images_en (1'b1),
.o_SAD (SADB),
.o_en ()
);
//显示跟踪到的目标的位置
//显示跟踪到的目标的位置
//显示跟踪到的目标的位置
wire[11:0]sCCD_R1;
wire[11:0]sCCD_G1;
wire[11:0]sCCD_B1;
disp disp_u(
.i_clk (CAMERA_PIXCLK),
.i_rst (~DLY_RST_1),
.i_track(o_tracker),
.i_sadR (SADR),
.i_sadG (SADG),
.i_sadB (SADB),
.i_R (sCCD_R0),
.i_G (sCCD_G0),
.i_B (sCCD_B0),
.o_R (sCCD_R1),
.o_G (sCCD_G1),
.o_B (sCCD_B1)
);
assign sCCD_R = sCCD_R1;
assign sCCD_G = sCCD_G1;
assign sCCD_B = sCCD_B1;
//frame number display
SEG7_LUT_8 u5 ( .oSEG0(HEX0),.oSEG1(HEX1),
.oSEG2(HEX2),.oSEG3(HEX3),
.oSEG4(HEX4),.oSEG5(HEX5),
.oSEG6(HEX6),.oSEG7(HEX7),
.iDIG(Frame_Cont[31:0])
);
//pll
sdram_pll u6 (
.inclk0(CLOCK2_50),
.c0(sdram_ctrl_clk),
.c1(DRAM_CLK),
.c2(CAMERA_XCLKIN), // cmos sensor main clock input,25M
.c3(lcd_clk) // cmos sensor lcd pix clock,33M
);
//frame buffer
Sdram_Control u7 ( // HOST Side
.RESET_N(KEY[0]),
.CLK(sdram_ctrl_clk),
// FIFO Write Side 1
.WR1_DATA(1'b0,sCCD_G[11:7],sCCD_B[11:2]),
.WR1(sCCD_DVAL),
.WR1_ADDR(0),
.WR1_MAX_ADDR(800*480/2),
.WR1_LENGTH(8'h80),
.WR1_LOAD(!DLY_RST_0),
.WR1_CLK(CAMERA_PIXCLK),
// FIFO Write Side 2
.WR2_DATA( 1'b0,sCCD_G[6:2],sCCD_R[11:2]),
//.WR2_DATA( 6'b000000,10'b1111111111),
.WR2(sCCD_DVAL),
.WR2_ADDR(23'h100000),
.WR2_MAX_ADDR(23'h100000+800*480/2),
.WR2_LENGTH(8'h80),
.WR2_LOAD(!DLY_RST_0),
.WR2_CLK(CAMERA_PIXCLK),
// FIFO Read Side 1
.RD1_DATA(Read_DATA1),
.RD1(Read),
.RD1_ADDR(0),
.RD1_MAX_ADDR(800*480/2),
.RD1_LENGTH(8'h80),
.RD1_LOAD(!DLY_RST_0),
.RD1_CLK(~LTP_CTRL_CLK),
// FIFO Read Side 2
.RD2_DATA(Read_DATA2),
.RD2(Read),
.RD2_ADDR(23'h100000),
.RD2_MAX_ADDR(23'h100000+800*480/2),
.RD2_LENGTH(8'h80),
.RD2_LOAD(!DLY_RST_0),
.RD2_CLK(~LTP_CTRL_CLK),
// SDRAM Side
.SA(DRAM_ADDR),
.BA(DRAM_BA),
.CS_N(DRAM_CS_N),
.CKE(DRAM_CKE),
.RAS_N(DRAM_RAS_N),
.CAS_N(DRAM_CAS_N),
.WE_N(DRAM_WE_N),
.DQ(DRAM_DQ),
.DQM(DRAM_DQM)
);
//cmos sensor configuration
I2C_CCD_Config u8 ( // Host Side
.iCLK(CLOCK2_50),
.iRST_N(DLY_RST_2),
.iEXPOSURE_ADJ(KEY[1]),
.iEXPOSURE_DEC_p(SW[0]),
.iMIRROR_SW(SW[17]),
// I2C Side
.I2C_SCLK(CAMERA_SCLK),
.I2C_SDAT(CAMERA_SDATA)
);
//ltp controller
ltp_controller u1 ( .iCLK(LTP_CTRL_CLK),
.iRST_n(DLY_RST_2),
// sdram side
.iREAD_DATA1(Read_DATA1),
.iREAD_DATA2(Read_DATA2),
.oREAD_SDRAM_EN(Read),
// lcd side
.oLCD_R(lcd_r),
.oLCD_G(lcd_g),
.oLCD_B(lcd_b),
.oHD(lcd_hs),
.oVD(lcd_vs),
.oDEN()
);
4.FPGA测试
可以单独做modelsim仿真
的modelsim仿真如下所示:
oframe2为延迟一帧后的视频,然后oframe1和oframe2就可以做差分了。
的modelsim仿真如下所示:
将该仿真图放大,可以看到:
由于中值滤波,是将3*3窗口内的像素值,取其中间值作为滤波输出,所以滤波后的图像像素数据o_median相对于输入像素i_din,码率上为原来的1/9。其中o_write_CLK为输出像素值o_median所对应的时钟频率。
的modelsim仿真如下所示:
的modelsim仿真如下所示:
对于满足阈值范围的,o_tacker取值1,否则取值0.
A10-48
以上是关于FPGA目标跟踪基于FPGA的帧差法和SAD匹配算法的目标跟踪实现的主要内容,如果未能解决你的问题,请参考以下文章
中值滤波+SAD匹配跟踪基于verilog编程开发的FPGA中值滤波和SAD模板匹配跟踪
图像识别基于帧差法和颜色空间实现火灾检测matlab源码GUI
图像识别基于帧差法和颜色空间实现火灾检测matlab源码GUI
图像识别基于帧差法和颜色空间实现火灾检测matlab源码GUI