赞
踩
quartusii12.1
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结构如下所示:
- //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()
- );
可以单独做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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。