基于FPGA的帧差法仿真实现
一、帧差法的原理及应用
帧差法就是帧间差分法,帧差法是最为常用的行动目标检测措施之一,原理即是在图像序列邻接两帧或三帧间基于像素做差分运算来获取。率先,将邻接帧图像对应像素值相减获得差分图像,然后对差分图像二值化,在环境亮度改变不大的情形下,对应像素值改变小于预先确定的阈值时,能够感受这里为背景像素。假如图像区域的像素值改变很大,能够感受这是由于图像中行动物体引起的,将这些区域符号为前景像素,利用符号的像素区域能够确定行动目标在图像中的位置。由于邻接两帧间的工夫间隔极其短,用前一帧图像作为目前帧的背景模型具有较好的实时性,其背景不聚集,且更新速度快、算法容易、计算量小。算法的不足在于对环境噪声较为敏感,阈值的抉择相当关键,抉择过低不足以压抑图像中的噪声,过高则疏忽了图像中有用的改变。对于比拟大的、颜色统一的行动目标,有可能在目标内部发生抽象,无法全面地提取行动目标。多数应用于选择十字路口监控录像作为实验材料,检测过往车辆动态,也能为后期机器识别打下基础。
帧差法主要通过下面式子实现,其中 x1 和 x2 分别为当前帧和上一帧同一位置坐标的像素点灰度值,T 为预设的参考分割阈值,y 为最终输出的二值结果
二、帧差分法实现步骤
1、实验框图
2、模块介绍
a、 imread_framel :此模块用于读取事先准备好需要进行帧差法的两帧或多帧图片。
b、 Vga_crt:此模块用于产生后续模块所需时序。
c、 Hvcount :此模块用于对后续模块进行时序同步。
d、 Framel_diff :此模块用于帧差法的实现。
e、 Imwrite_fra :此模块用于读取帧差之后的结果。
三、帧差法的FPGA仿真实现
帧差法的原理比较简单,就是实时图像的相邻两帧或者三帧做差,FPGA的实现的难点在于大部分FPGA的内部存储(BRAM)不足以存取一幅完整图像的数据,这时就需要借助外部的SDRAM或者DDR等存储。
帧差法仿真源码展示:
1. /******************************************************
2. // Project Name:Frame_Difference
3. //
4. // Author:Lee
5. // 微信公众号:FPGA开源工作室
6. *******************************************************/
7. `timescale 1ns / 1ps
8.
9. module Frame_Difference #(
10. parameter IW = 800,
11. parameter IH = 600,
12. parameter DW = 24
13. )(
14. input PixelClk,
15. input reset_n,
16. input [DW-1:0] i_rgb,
17. input i_hs,
18. input i_vs,
19. input i_de,
20. output [DW-1:0] o_rgb,
21. output o_hs,
22. output o_vs,
23. output o_de
24. );
25.
26.
27. reg we;
28. reg rd;
29. reg [20:0] waddr;//800*600
30. reg [20:0] raddr;
31. wire [DW-1:0] dout;
32. reg [DW-1:0] rgb_r;
33. reg [DW-1:0] dout_r;
34. reg hs_r0;
35. reg vs_r0;
36. reg de_r0;
37.
38. reg hs_r1;
39. reg vs_r1;
40. reg de_r1;
41.
42. reg hs_r2;
43. reg vs_r2;
44. reg de_r2;
45.
46. assign o_hs = hs_r2;
47. assign o_vs = vs_r2;
48. assign o_de = de_r2;
49. assign o_rgb = dout_r;
50. always @(posedge PixelClk )begin
51. rgb_r <= i_rgb;
52. hs_r0 <= i_hs;
53. vs_r0 <= i_vs;
54. de_r0 <= i_de;
55.
56. hs_r1 <= hs_r0 ;
57. vs_r1 <= vs_r0 ;
58. de_r1 <= de_r0 ;
59.
60. hs_r2 <= hs_r1 ;
61. vs_r2 <= vs_r1 ;
62. de_r2 <= de_r1 ;
63. end
64. always @(posedge PixelClk or negedge reset_n)begin
65. if(de_r1)
66. //dout_r <= dout - rgb_r; //Frame Difference
67. dout_r <= rgb_r - dout; //Frame Difference
68. else
69. dout_r <= 0;
70. end
71.
72. always @(posedge PixelClk or negedge reset_n)begin
73. if(!reset_n) begin
74. rd <= 0;
75. we <= 0;
76. raddr <= 0;
77. waddr <= 0;
78. end
79. else if(i_vs == 0) begin
80. rd <= 0;
81. we <= 0;
82. raddr <= 0;
83. waddr <= 0;
84. end
85. else if(i_de) begin
86. rd <= 1;
87. raddr <= raddr 1;
88. we <= 1;
89. waddr <= waddr 1;
90. end
91. else begin
92. rd <= 0;
93. we <= 0;
94. raddr <= raddr;
95. waddr <= waddr;
96. end
97. end
98.
99. Frame_Ram#(
100. .IW(IW),
101. .IH(IH),
102. .DW(DW)
103. )U_Frame_Ram(
104. .clk(PixelClk),
105. .reset_n(reset_n),
106. .we(we),
107. .rd(rd),
108. .waddr(waddr),//1920*1080
109. .raddr(raddr),
110. .din(i_rgb),
111. .dout(dout)
112. );
113.
114. endmodule
115.
116.
117. module Frame_Ram#(
118. parameter IW = 800,
119. parameter IH = 600,
120. parameter DW = 24
121. )(
122. input clk,
123. input reset_n,
124. input we,
125. input rd,
126. input [20:0] waddr,//800*600
127. input [20:0] raddr,
128. input [DW-1:0] din,
129. output [DW-1:0] dout
130. );
131.
132. //reg [DW-1:0] mem[0:IW*IH];
133. reg [DW-1:0] mem[IW*IH:0];
134.
135. reg [DW-1:0] rdata;
136. assign dout = rdata;
137.
138. integer n;
139. always @(posedge clk or negedge reset_n) begin
140. if(!reset_n) begin
141. for(n = 0; n <IW*IH; n = n 1) mem[n] <= 0;//sim only
142. rdata <= 0;
143. end
144. else begin
145. if(rd) rdata <= mem[raddr]; else rdata <= 0;
146. if(we) mem[waddr] <= din;
147. end
148. end
149.
150. endmodule
代码解释:
帧差法代码主要分为两个模块一个RAM用于存储一帧图像,Frame_Difference模块用于实现两帧之间点对点做差。
实验图1
实验图2
实验图3
结果图1
结果图2
实验结果分析:
实验图1为第一帧图像,实验图2为第二帧图像,实验图3为第三帧图像,第二帧和第三帧做差如图结果1所示,结果2为抓取结果1的位置。
在文章的末尾特别感谢网友迟茶枯对本文一二节内容的贡献。