FPGA图像处理-均值滤波
简介
上一篇博客介绍了如何在FPGA中利用shift-ram实现行缓存,然后得到3x3卷积模板,这回就来利用这个3x3窗口进行均值滤波。
均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标象素为中心的周围 8 个像素,构成一个滤波模板,即去掉目标像素本身),再用模板中的全体像素的平均值来代替原来像素值。

output = (p11 + p12 + p13 + p21 + p23 + p31 + p32 + p33) / 8
根据公式,可以将其分解为三级流水线:
- 第一级处理3x3窗口每一行的加法
- 第二级处理全部加法
- 第三级处理移位,即除以8
模块简介
为了简单起见,输入输出都是valid+data形式:
module mean_filter(input clk,input rst_n,input iValid,input [7:0] iData,output oValid,output [7:0] oData
);
均值滤波算法的实现
获取3x3卷积模板
上一篇博客有介绍如何获取3x3卷积模板,感兴趣的可以看看
需要注意获取3x3卷积模板消耗了2时钟周期。
filter_3x3 inst_filter_3x3(.clk (clk),.rst_n (rst_n),.iValid (iValid),.iData (iData),.oValid (filter_oValid),.oData_11 (filter_11), .oData_12 (filter_12), .oData_13 (filter_13),.oData_21 (filter_21), .oData_22 (filter_22), .oData_23 (filter_23),.oData_31 (filter_31), .oData_32 (filter_32), .oData_33 (filter_33)
);
第一级流水线:处理窗口每一行的和
// 3x3模板的每一行的和
reg [10:0] add_1, add_2, add_3;always @(posedge clk, negedge rst_n) beginif(!rst_n) beginadd_1 <= 0;add_2 <= 0;add_3 <= 0;end else beginadd_1 <= filter_11 + filter_12 + filter_13;add_2 <= filter_21 + filter_23; // 中心值不参与运算add_3 <= filter_31 + filter_32 + filter_33;end
end
第二级流水线:将窗口每一行的和相加得到总和
// 3x3模板的总和
reg [10:0] add_all;// step2 加法运算,总和
always @(posedge clk, negedge rst_n) beginif(!rst_n)add_all <= 0;elseadd_all <= add_1 + add_2 + add_3;
end
第三级流水线:移位得到均值结果
// 3x3模板总和/8
reg [7:0] mean_value;// 右移3位即除以8,得出均值
always @(posedge clk, negedge rst_n) beginif(!rst_n)mean_value <= 0;elsemean_value <= add_all[10:3];
end
获取3x3卷积模板消耗了2时钟周期,均值滤波消耗了3时钟周期,所以输出值延后输入值5个时钟周期,oValid信号也要进行延迟,比iValid慢5个时钟周期。
testbench
和之前类似,仿真3行像素,每行640个像素点。
`timescale 1ps/1ps
module mean_filter_tb;reg clk = 1'b1;always #10 clk = ~clk;reg rst_n = 1'b0;reg iValid = 1'b0;reg [7:0] iData = 0;wire oValid;wire [7:0] oData;initial begin#20 rst_n <= 1'b1;#20 iValid <= 1'b1;// 第一行数据repeat(640) beginiData <= $random;#20;endiValid <= 1'b0;// 第二行数据#100 iValid <= 1'b1;repeat(640) beginiData <= $random;#20;endiValid <= 1'b0;// 第三行数据#100 iValid <= 1'b1;repeat(640) beginiData <= $random;#20;end#500 $stop;endmean_filter inst_mean_filter(.clk (clk),.rst_n (rst_n),.iValid (iValid),.iData (iData),.oValid (oValid),.oData (oData));
endmodule
波形分析
第一行前3个像素为36,129,9

第二行前3个像素为235,248,242

第三行前三个像素为121,205,146

第一个完整模板的均值:(36 + 129 + 9 + 235 + 242 + 121 + 205 + 146) / 8 = 140
模板中间的像素248不参与计算,当146进入模板后的第五个时钟周期,输出了140,验证正确。
下一个均值:(129 + 9 + 99 + 248 + 137 + 205 + 146 + 69) / 8 = 130
模板中间的242不参与计算,可以看到,140后面输出的就是130,验证正确。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
