当前位置:   article > 正文

【FPGA目标跟踪】基于FPGA的帧差法和SAD匹配算法的目标跟踪实现_帧差法 fpga

帧差法 fpga

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.核心程序

  1. //reset signals
  2. Reset_Delay u2 ( .iCLK(CLOCK2_50),
  3. .iRST(KEY[0]),
  4. .oRST_0(DLY_RST_0),
  5. .oRST_1(DLY_RST_1),
  6. .oRST_2(DLY_RST_2),
  7. .oRST_3(DLY_RST_3), //auto-start start point
  8. .oRST_4(DLY_RST_4) //auto-start end point
  9. );
  10. //cmos sensor capture
  11. CCD_Capture u3 ( .oDATA(mCCD_DATA),
  12. .oDVAL(mCCD_DVAL),
  13. .oX_Cont(X_Cont),
  14. .oY_Cont(Y_Cont),
  15. .oFrame_Cont(Frame_Cont),
  16. .iDATA(rCCD_DATA),
  17. .iFVAL(rCCD_FVAL),
  18. .iLVAL(rCCD_LVAL),
  19. .iSTART((!KEY[3])| auto_start),
  20. .iEND(!KEY[2]),
  21. .iCLK(~CAMERA_PIXCLK),
  22. .iRST(DLY_RST_2)
  23. );
  24. //raw data to RGB conversion
  25. wire [11:0] sCCD_R_;
  26. wire [11:0] sCCD_G_;
  27. wire [11:0] sCCD_B_;
  28. RAW2RGB u4 ( .iCLK(CAMERA_PIXCLK),
  29. .iRST_n(DLY_RST_1),
  30. .iData(mCCD_DATA),
  31. .iDval(mCCD_DVAL),
  32. .oRed(sCCD_R_),
  33. .oGreen(sCCD_G_),
  34. .oBlue(sCCD_B_),
  35. .oDval(sCCD_DVAL),
  36. .iMIRROR(SW[17]),
  37. .iX_Cont(X_Cont),
  38. .iY_Cont(Y_Cont)
  39. );
  40. //图像的中值滤波
  41. //图像的中值滤波
  42. //图像的中值滤波
  43. wire [11:0] sCCD_R0;
  44. wire [11:0] sCCD_G0;
  45. wire [11:0] sCCD_B0;
  46. filter media_tops_u1(
  47. .i_clk (CAMERA_PIXCLK),
  48. .i_rst (~DLY_RST_1),
  49. .i_din (sCCD_R_),
  50. .o_address (),
  51. .o_enable0 (),//NC
  52. .o_median (sCCD_R0),
  53. .o_enable1 (),//NC
  54. .o_frame_flag (),
  55. .o_Write_Address(),
  56. .o_Write_CLK ()
  57. );
  58. filter media_tops_u2(
  59. .i_clk (CAMERA_PIXCLK),
  60. .i_rst (~DLY_RST_1),
  61. .i_din (sCCD_G_),
  62. .o_address (),
  63. .o_enable0 (),//NC
  64. .o_median (sCCD_G0),
  65. .o_enable1 (),//NC
  66. .o_frame_flag (),
  67. .o_Write_Address(),
  68. .o_Write_CLK ()
  69. );
  70. filter media_tops_u3(
  71. .i_clk (CAMERA_PIXCLK),
  72. .i_rst (~DLY_RST_1),
  73. .i_din (sCCD_B_),
  74. .o_address (),
  75. .o_enable0 (),//NC
  76. .o_median (sCCD_B0),
  77. .o_enable1 (),//NC
  78. .o_frame_flag (),
  79. .o_Write_Address(),
  80. .o_Write_CLK ()
  81. );
  82. //彩色图,转换为灰度图,Y = 0.3R + 0.59G + 0.11B
  83. //彩色图,转换为灰度图,Y = 0.3R + 0.59G + 0.11B
  84. //彩色图,转换为灰度图,Y = 0.3R + 0.59G + 0.11B
  85. //0.3 = 1/4+1/32+1/64+1/512+1/1024
  86. //0.59 = 1/2+1/16+1/64+1/128+1/256
  87. //0.11 = 1/16+1/32+1/64
  88. wire[11:0]R1;
  89. wire[11:0]G1;
  90. wire[11:0]B1;
  91. wire[11:0]GRAY;
  92. //0.3 = 1/4+1/32+1/64+1/512+1/1024
  93. 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]} +
  94. {sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11],sCCD_R0[11:6]} +
  95. {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]} +
  96. {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]};
  97. //0.59 = 1/2+1/16+1/64+1/128+1/256
  98. 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]} +
  99. {sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11],sCCD_G0[11:6]} +
  100. {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]} +
  101. {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]};
  102. //0.11 = 1/16+1/32+1/64
  103. assign B1 = {sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11:4]} +
  104. {sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_G0[11:5]} +
  105. {sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11],sCCD_B0[11:6]};
  106. assign GRAY = R1+G1+B1;
  107. //获得前后2帧,进行差分计算
  108. //获得前后2帧,进行差分计算
  109. //获得前后2帧,进行差分计算
  110. wire[11:0]Frame1;
  111. wire[11:0]Frame2;
  112. Delay_frame Delay_frame_u(
  113. .i_clk (CAMERA_PIXCLK),
  114. .i_rst (~DLY_RST_1),
  115. .i_din (GRAY),
  116. .o_frame1(Frame1),
  117. .o_frame2(Frame2)
  118. );
  119. //差分
  120. wire signed[11:0]Framediff;
  121. assign Framediff = Frame1-Frame2;
  122. wire signed[11:0]o_tracker;
  123. tracker tracker_u(
  124. .i_clk (CAMERA_PIXCLK),
  125. .i_rst (~DLY_RST_1),
  126. .i_data (Framediff),
  127. .o_tracker (o_tracker)
  128. );
  129. //基于SAD的模板匹配
  130. //基于SAD的模板匹配
  131. //基于SAD的模板匹配
  132. wire[23:0]SADR;
  133. SAD_tops1 SAD_tops1_u1(
  134. .i_clk (CAMERA_PIXCLK),
  135. .i_rst (~DLY_RST_1),
  136. .i_en (1'b1),
  137. .i_images (sCCD_R0),
  138. .i_images_en (1'b1),
  139. .o_SAD (SADR),
  140. .o_en ()
  141. );
  142. wire[23:0]SADG;
  143. SAD_tops1 SAD_tops1_u2(
  144. .i_clk (CAMERA_PIXCLK),
  145. .i_rst (~DLY_RST_1),
  146. .i_en (1'b1),
  147. .i_images (sCCD_G0),
  148. .i_images_en (1'b1),
  149. .o_SAD (SADG),
  150. .o_en ()
  151. );
  152. wire[23:0]SADB;
  153. SAD_tops1 SAD_tops1_u3(
  154. .i_clk (CAMERA_PIXCLK),
  155. .i_rst (~DLY_RST_1),
  156. .i_en (1'b1),
  157. .i_images (sCCD_B0),
  158. .i_images_en (1'b1),
  159. .o_SAD (SADB),
  160. .o_en ()
  161. );
  162. //显示跟踪到的目标的位置
  163. //显示跟踪到的目标的位置
  164. //显示跟踪到的目标的位置
  165. wire[11:0]sCCD_R1;
  166. wire[11:0]sCCD_G1;
  167. wire[11:0]sCCD_B1;
  168. disp disp_u(
  169. .i_clk (CAMERA_PIXCLK),
  170. .i_rst (~DLY_RST_1),
  171. .i_track(o_tracker),
  172. .i_sadR (SADR),
  173. .i_sadG (SADG),
  174. .i_sadB (SADB),
  175. .i_R (sCCD_R0),
  176. .i_G (sCCD_G0),
  177. .i_B (sCCD_B0),
  178. .o_R (sCCD_R1),
  179. .o_G (sCCD_G1),
  180. .o_B (sCCD_B1)
  181. );
  182. assign sCCD_R = sCCD_R1;
  183. assign sCCD_G = sCCD_G1;
  184. assign sCCD_B = sCCD_B1;
  185. //frame number display
  186. SEG7_LUT_8 u5 ( .oSEG0(HEX0),.oSEG1(HEX1),
  187. .oSEG2(HEX2),.oSEG3(HEX3),
  188. .oSEG4(HEX4),.oSEG5(HEX5),
  189. .oSEG6(HEX6),.oSEG7(HEX7),
  190. .iDIG(Frame_Cont[31:0])
  191. );
  192. //pll
  193. sdram_pll u6 (
  194. .inclk0(CLOCK2_50),
  195. .c0(sdram_ctrl_clk),
  196. .c1(DRAM_CLK),
  197. .c2(CAMERA_XCLKIN), // cmos sensor main clock input,25M
  198. .c3(lcd_clk) // cmos sensor lcd pix clock,33M
  199. );
  200. //frame buffer
  201. Sdram_Control u7 ( // HOST Side
  202. .RESET_N(KEY[0]),
  203. .CLK(sdram_ctrl_clk),
  204. // FIFO Write Side 1
  205. .WR1_DATA({1'b0,sCCD_G[11:7],sCCD_B[11:2]}),
  206. .WR1(sCCD_DVAL),
  207. .WR1_ADDR(0),
  208. .WR1_MAX_ADDR(800*480/2),
  209. .WR1_LENGTH(8'h80),
  210. .WR1_LOAD(!DLY_RST_0),
  211. .WR1_CLK(CAMERA_PIXCLK),
  212. // FIFO Write Side 2
  213. .WR2_DATA( {1'b0,sCCD_G[6:2],sCCD_R[11:2]}),
  214. //.WR2_DATA( {6'b000000,10'b1111111111}),
  215. .WR2(sCCD_DVAL),
  216. .WR2_ADDR(23'h100000),
  217. .WR2_MAX_ADDR(23'h100000+800*480/2),
  218. .WR2_LENGTH(8'h80),
  219. .WR2_LOAD(!DLY_RST_0),
  220. .WR2_CLK(CAMERA_PIXCLK),
  221. // FIFO Read Side 1
  222. .RD1_DATA(Read_DATA1),
  223. .RD1(Read),
  224. .RD1_ADDR(0),
  225. .RD1_MAX_ADDR(800*480/2),
  226. .RD1_LENGTH(8'h80),
  227. .RD1_LOAD(!DLY_RST_0),
  228. .RD1_CLK(~LTP_CTRL_CLK),
  229. // FIFO Read Side 2
  230. .RD2_DATA(Read_DATA2),
  231. .RD2(Read),
  232. .RD2_ADDR(23'h100000),
  233. .RD2_MAX_ADDR(23'h100000+800*480/2),
  234. .RD2_LENGTH(8'h80),
  235. .RD2_LOAD(!DLY_RST_0),
  236. .RD2_CLK(~LTP_CTRL_CLK),
  237. // SDRAM Side
  238. .SA(DRAM_ADDR),
  239. .BA(DRAM_BA),
  240. .CS_N(DRAM_CS_N),
  241. .CKE(DRAM_CKE),
  242. .RAS_N(DRAM_RAS_N),
  243. .CAS_N(DRAM_CAS_N),
  244. .WE_N(DRAM_WE_N),
  245. .DQ(DRAM_DQ),
  246. .DQM(DRAM_DQM)
  247. );
  248. //cmos sensor configuration
  249. I2C_CCD_Config u8 ( // Host Side
  250. .iCLK(CLOCK2_50),
  251. .iRST_N(DLY_RST_2),
  252. .iEXPOSURE_ADJ(KEY[1]),
  253. .iEXPOSURE_DEC_p(SW[0]),
  254. .iMIRROR_SW(SW[17]),
  255. // I2C Side
  256. .I2C_SCLK(CAMERA_SCLK),
  257. .I2C_SDAT(CAMERA_SDATA)
  258. );
  259. //ltp controller
  260. ltp_controller u1 ( .iCLK(LTP_CTRL_CLK),
  261. .iRST_n(DLY_RST_2),
  262. // sdram side
  263. .iREAD_DATA1(Read_DATA1),
  264. .iREAD_DATA2(Read_DATA2),
  265. .oREAD_SDRAM_EN(Read),
  266. // lcd side
  267. .oLCD_R(lcd_r),
  268. .oLCD_G(lcd_g),
  269. .oLCD_B(lcd_b),
  270. .oHD(lcd_hs),
  271. .oVD(lcd_vs),
  272. .oDEN()
  273. );

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/134978
推荐阅读
相关标签
  

闽ICP备14008679号