图像处理之均值滤波"/>
FPGA图像处理之均值滤波
1.均值滤波算法的理论
所有的滤波算法都是通过当前像素周边的像素,以一定的权重加权计算滤波后的结果。因此主要涉及两个变量:窗口内像素的权重值,以及窗口的大小。滤波的窗口有3x3、5x5、7x7、11x11等,窗口的尺度越大,相应的计算量越大,效果也越明显。
均值滤波可以简单的表示为在邻域窗3x3内,所有的像素权重相同,简单加权后求平均值,因此,图像中的噪声并没有被去除,只是被平均了而已。此外,均值滤波除了抑制噪声,也有平滑纹理的效果。如果窗口很大,也会产生模糊的效果。
2.均值滤波的FPGA实现
通过在图像上进行滑窗处理,可以获得以目标像素为中心的3x3窗口,从图像左上角开始,每次计算完当前像素后,再往右滑动一个像素,以新的窗口计算新的像素;当窗口滑动到行内最后一个像素并完成计算后,另起一行重新开始滑窗运算操作。
为了生成以目标像素为中心的3x3窗口,需要缓存3行像素,但在设计时只需要缓存两行像素,第三行像素实时输入即可。以FIFO方式对行像素进行缓存,并以菊花链的形式连接行缓存,即将当前行缓存的输出接到下一个行缓存的输入。
矩阵代码:
module Matrix_Generate_3x3_8Bit
#(parameter [10:0] IMG_HDISP = 11'd640;parameter [10:0] IMG_VDISP = 11'd480;parameter [10:0] DELAY_NUM = 11'd10
)
(input clk,input rst_n,input per_img_vsync,input per_img_href,input [7:0] per_img_gray,output matrix_img_vsync,output matrix_img_href,output matrix_top_edge_flag,output matrix_bottom_edge_flag,output matrix_left_edge_flag,output matrix_right_edge_flag,output reg [7:0] matrix_p11;output reg [7:0] matrix_p12;output reg [7:0] matrix_p13;output reg [7:0] matrix_p21;output reg [7:0] matrix_p22;output reg [7:0] matrix_p23;output reg [7:0] matrix_p31;output reg [7:0] matrix_p32;output reg [7:0] matrix_p33;
);reg [10:0] hcnt;always@(posedge clk or rst_n)beginif(!rst_n)hcnt <= 11'b0;else beginif(per_img_href == 1'b1)hcnt <= hcnt + 1'b1;else hcnt <= 11'b0;endendreg per_img_href_dly;always@(posedge clk or negedge rst_n)beginif(!rst_n)per_img_href_dly <= 1'b0;elseper_img_href_dly <= per_img_href;endwire img_href_neg = ~per_img_href & per_img_href_dly;reg [10:0] vcnt;always@(posedge clk or negedge rst_n)beginif(!rst_n)vcnt <= 11'b0;else beginif(per_img_vsync == 1'b0)vcnt <= 11'b0;else if(img_href_neg == 1'b1)vcnt <= vcnt + 1'b1;else vcnt <= vcnt;endendreg [10:0] extend_last_row_cnt;always@(posedge clk or negedge rst_n)beginif(!rst_n)extend_last_row_cnt <= 11'b0;else beginif((per_img_href == 1'b1)&&(vcnt == IMG_VDISP - 1'b1)&&(hcnt==IMG_HDISP - 1'b1)extend_last_row_cnt <= extend_last_row_cnt +1'b1;elseextend_last_row_cnt <= 11'b0;endendwire extend_last_row_en = (extend_last_row_cnt > DELAY_NUM)wire fifol_wenb;wire [7:0] fifol_wdata;wire fifol_renb;wire [7:0] fifol_rdata;wire fifo2_wdata;wire [7:0] fifo2_wdata;wire fifo2_renb;wire [7:0] fifo2_rdata;assign fifol_wenb = per_img_href;assign fifol_wdata = per_img_gray;assign fifo1_renb = per_img_href & (vcnt > 11'b0) | extend_last_row_en;assign fifo2_wenb = per_img_href & (vcnt > 11'b0);assign fifo2_wdata = fifo1_rdata;assign fifo2_renb = per_img_href & (vcnt > 11'b1) | extend_last_row_en;sync_fifo
#(.C_FIFO_WIDTH (8 ),.C_FIFO_DEPTH (1024 )
)
u1_sync_fifo
(.rst (~rst_n ),.clk (clk ),.wr_en (fifo1_wenb ),.din (fifo1_wdata), .full ( ),.rd_en (fifo1_renb ),.dout (fifo1_rdata),.empty ( ),.data_count ( )
);sync_fifo
#(.C_FIFO_WIDTH (8 ),.C_FIFO_DEPTH (1024 )
)
u2_sync_fifo
(.rst (~rst_n ),.clk (clk ),.wr_en (fifo2_wenb ),.din (fifo2_wdata), .full ( ),.rd_en (fifo2_renb ),.dout (fifo2_rdata),.empty ( ),.data_count ( )
);
// Read data from fifo
always @(posedge clk or negedge rst_n)
beginif(!rst_n)begin{matrix_p11, matrix_p12, matrix_p13} <= 24'h0;{matrix_p21, matrix_p22, matrix_p23} <= 24'h0;{matrix_p31, matrix_p32, matrix_p33} <= 24'h0;endelsebegin{matrix_p11, matrix_p12, matrix_p13} <= {matrix_p12, matrix_p13, fifo2_rdata}; // 1st row input{matrix_p21, matrix_p22, matrix_p23} <= {matrix_p22, matrix_p23, fifo1_rdata}; // 2nd row input{matrix_p31, matrix_p32, matrix_p33} <= {matrix_p32, matrix_p33, per_img_gray}; // 3rd row inputend
endreg [1:0] vsync;
reg [1:0] href;
reg [1:0] top_edge_flag;
reg [1:0] bottom_edge_flag;
reg [1:0] left_edge_flag;
reg [1:0] right_edge_flag;always @(posedge clk or negedge rst_n)
beginif(!rst_n)vsync <= 2'b0;elsebeginif((per_img_href == 1'b1)&&(vcnt == 11'd1)&&(hcnt == 11'b0))vsync[0] <= 1'b1;else if(extend_last_row_cnt == DELAY_NUM + IMG_HDISP)vsync[0] <= 1'b0;elsevsync[0] <= vsync[0];vsync[1] <= vsync[0];end
endalways @(posedge clk or negedge rst_n)
beginif(!rst_n)beginhref <= 2'b0;top_edge_flag <= 2'b0;bottom_edge_flag <= 2'b0;left_edge_flag <= 2'b0;right_edge_flag <= 2'b0;endelsebeginhref[0] <= per_img_href & (vcnt > 11'b0) | extend_last_row_en;href[1] <= href[0];top_edge_flag[0] <= per_img_href & (vcnt == 11'd1);top_edge_flag[1] <= top_edge_flag[0];bottom_edge_flag[0] <= extend_last_row_en;bottom_edge_flag[1] <= bottom_edge_flag[0];left_edge_flag[0] <= per_img_href & (vcnt > 11'b0) & (hcnt == 11'b0) | (extend_last_row_cnt == DELAY_NUM + 1'b1);left_edge_flag[1] <= left_edge_flag[0];right_edge_flag[0] <= per_img_href & (vcnt > 11'b0) & (hcnt == IMG_HDISP - 1'b1) | (extend_last_row_cnt == DELAY_NUM + IMG_HDISP);right_edge_flag[1] <= right_edge_flag[0];end
endassign matrix_img_vsync = vsync[1];
assign matrix_img_href = href[1];
assign matrix_top_edge_flag = top_edge_flag[1];
assign matrix_bottom_edge_flag = bottom_edge_flag[1];
assign matrix_left_edge_flag = left_edge_flag[1];
assign matrix_right_edge_flag = right_edge_flag[1];endmodule
均值算法
module mean_filter_proc
#(
parameter [10:0] IMG_HDISP = 11’d640, // 640*480
parameter [10:0] IMG_VDISP = 11’d480
)
(
input wire clk ,
input wire rst_n ,
// Image data prepared to be processed
input wire per_img_vsync , // Prepared Image data vsync valid signal
input wire per_img_href , // Prepared Image data href vaild signal
input wire [7:0] per_img_gray , // Prepared Image brightness input// Image data has been processed
output reg post_img_vsync , // processed Image data vsync valid signal
output reg post_img_href , // processed Image data href vaild signal
output reg [7:0] post_img_gray // processed Image brightness output
);
//----------------------------------------------------------------------
// Generate 8Bit 3X3 Matrix
wire matrix_img_vsync;
wire matrix_img_href;
wire matrix_top_edge_flag;
wire matrix_bottom_edge_flag;
wire matrix_left_edge_flag;
wire matrix_right_edge_flag;
wire [7:0] matrix_p11;
wire [7:0] matrix_p12;
wire [7:0] matrix_p13;
wire [7:0] matrix_p21;
wire [7:0] matrix_p22;
wire [7:0] matrix_p23;
wire [7:0] matrix_p31;
wire [7:0] matrix_p32;
wire [7:0] matrix_p33;
Matrix_Generate_3X3_8Bit
#(
.IMG_HDISP (IMG_HDISP ),
.IMG_VDISP (IMG_VDISP )
)
u_Matrix_Generate_3X3_8Bit
(
// global clock & reset
.clk (clk ),
.rst_n (rst_n ),
// Image data prepared to be processed
.per_img_vsync (per_img_vsync ), // Prepared Image data vsync valid signal
.per_img_href (per_img_href ), // Prepared Image data href vaild signal
.per_img_gray (per_img_gray ), // Prepared Image brightness input// Image data has been processed
.matrix_img_vsync (matrix_img_vsync ), // processed Image data vsync valid signal
.matrix_img_href (matrix_img_href ), // processed Image data href vaild signal
.matrix_top_edge_flag (matrix_top_edge_flag ), // processed Image top edge
.matrix_bottom_edge_flag(matrix_bottom_edge_flag), // processed Image bottom edge
.matrix_left_edge_flag (matrix_left_edge_flag ), // processed Image left edge
.matrix_right_edge_flag (matrix_right_edge_flag ), // processed Image right edge
.matrix_p11 (matrix_p11 ), // 3X3 Matrix output
.matrix_p12 (matrix_p12 ),
.matrix_p13 (matrix_p13 ),
.matrix_p21 (matrix_p21 ),
.matrix_p22 (matrix_p22 ),
.matrix_p23 (matrix_p23 ),
.matrix_p31 (matrix_p31 ),
.matrix_p32 (matrix_p32 ),
.matrix_p33 (matrix_p33 )
);
//----------------------------------------------------------------------
// calc sum of [p11,p12,p13;p21,p22,p23;p31,p32,p33]
reg [ 9:0] data_sum1;
reg [ 9:0] data_sum2;
reg [ 9:0] data_sum3;
reg [11:0] data_sum;
always @(posedge clk)
begin
data_sum1 <= matrix_p11 + matrix_p12 + matrix_p13;
data_sum2 <= matrix_p21 + matrix_p22 + matrix_p23;
data_sum3 <= matrix_p31 + matrix_p32 + matrix_p33;
data_sum <= data_sum1 + data_sum2 + data_sum3;
end
//----------------------------------------------------------------------
// avg_data = round(data_sum/9.0) -> avg_data = round(data_sum*3641 >> 15)
reg [22:0] data_mult;
always @(posedge clk)
begin
data_mult <= data_sum * 12’d3641;
end
reg [7:0] avg_data;
always @(posedge clk)
begin
avg_data <= data_mult[22:15] + data_mult[14];
end
//----------------------------------------------------------------------
// lag 4 clocks signal sync
reg [3:0] matrix_img_vsync_r1;
reg [3:0] matrix_img_href_r1;
reg [3:0] matrix_edge_flag_r1;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
matrix_img_vsync_r1 <= 4’b0;
matrix_img_href_r1 <= 4’b0;
matrix_edge_flag_r1 <= 4’b0;
end
else
begin
matrix_img_vsync_r1 <= {matrix_img_vsync_r1[2:0],matrix_img_vsync};
matrix_img_href_r1 <= {matrix_img_href_r1[2:0],matrix_img_href};
matrix_edge_flag_r1 <= {matrix_edge_flag_r1[2:0],matrix_top_edge_flag | matrix_bottom_edge_flag | matrix_left_edge_flag | matrix_right_edge_flag};
end
end
reg [7:0] matrix_p22_r1 [0:3];
always @(posedge clk)
begin
matrix_p22_r1[0] <= matrix_p22;
matrix_p22_r1[1] <= matrix_p22_r1[0];
matrix_p22_r1[2] <= matrix_p22_r1[1];
matrix_p22_r1[3] <= matrix_p22_r1[2];
end
//----------------------------------------------------------------------
// result output
always @(posedge clk)
begin
if(matrix_edge_flag_r1[3] == 1’b1)
post_img_gray <= matrix_p22_r1[3];
else
post_img_gray <= avg_data;
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
post_img_vsync <= 1’b0;
post_img_href <= 1’b0;
end
else
begin
post_img_vsync <= matrix_img_vsync_r1[3];
post_img_href <= matrix_img_href_r1[3];
end
end
endmodule
3.参考资料
1.基于MATLAB与FPGA的图像处理教程 (韩彬)
更多推荐
FPGA图像处理之均值滤波
发布评论