本帖最后由 雪孩爱雪 于 2020-1-27 23:05 编辑
背景知识
均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括
了其周围的临近像素(以目标像素为中心的周围 8 个像素,构成一个滤波模板,即去掉目标
像素本身),再用模板中的全体像素的平均值来代替原来像素值。
均值滤波也称为线性滤波,其采用的主要方法为邻域平均法。线性滤波的基本原理是用
均值代替原图像中的各个像素值,即对待处理的当前像素点(x,y),选择一个模板,该模
板由其近邻的若干像素组成,求模板中所有像素的均值,再把该均值赋予当前像素点(x,
y),作为处理后图像在该点上的灰度 g(x,y),即 g(x,y)=1/m ∑f(x,y) m 为该模
板中包含当前像素在内的像素总个数。
均值滤波本身存在着固有的缺陷,即它不能很好地保护图像细节,在图像去噪的同时也
破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点。
FPGA 的均值滤波算法实现步骤
如图 1 所示,中心点(x,y)为均值滤波将要处理的位置,
f(x,y)表示(x,y)点的像素值,
g(x,y)表示(x,y)点经过均值处理后的值。
均值滤波公式表示如下:
g(x,y)=1/8*(f(x-1,y-1)+f(x,y-1)+f(x+1,y-1)+f(x-1,y)+f(x+1,y)+f(x-1,y+1)+f(x,y+1)+f(x+1,y+1))------------------------------(1)
由(1)式我们看出(x,y)点的 3x3 像素点的均值等于其周围邻域的八个点的像素值之和
除以 8。
FPGA 实现步骤:
1>形成 3x3 矩阵像素
2>求周围邻域八个点的像素值之和 将3x3矩阵的中心像素的周围八个点求和,我们这里还是采取流水线的设计方法,来增加吞吐量,然后再求平均值代替目标像素的值
3>将结果右移三位(相当于除以 8)得到结果
我们要进行均值滤波首先要生成一个3x3矩阵。算法运算窗口一般采用奇数点的邻域来计算中值,最常用的窗口有3X3和5X5模型。 下面介绍3X3窗口的Verilog实现方法。 (1) 通过2个或者3个RAM的存储来实现3X3像素窗口; (2) 通过2个或者3个FIFO的存储来实现3X3像素窗口; (3) 通过2行或者3行Shift_RAM的存储来实现3X3像素窗口; 要想用实现均值滤波和中值滤波,必须要先生成3x3阵列,在Xilinx系列里,可以用调用IP核——shift_RAM,具体设置参数如图所示。 添加IP核 搜索IP核 IP核设置 hift register(RAM-based)ip 主要为了形成三行像素缓存。
这里Xilinx的shift_ram一次只能生成一行数据,所以我采用两个IP Core和正在输入的一行来生成三行数据
module line3(
input clk,
input [15:0] din,
input hs_valid_in,
output [15:0] dout,
output [15:0] dout_r0,
output [15:0] dout_r1,
output [15:0] dout_r2
);
line_buff line_buff0(
.D(din),
.CLK(clk),
.CE(hs_valid_in),
.Q(dout_r0)
);
line_buff line_buff1(
.D(dout_r0),
.CLK(clk),
.CE(hs_valid_in),
.Q(dout_r1)
);
line_buff line_buff2(
.D(dout_r1),
.CLK(clk),
.CE(hs_valid_in),
.Q(dout_r2)
);
assign dout = dout_r2;
endmodule 均值滤波算法(需要将图像转为灰度,转为灰度方法见之前发的): `timescale 1ns/1ps module mean_filter_3x3( input clk, input rst_n, input [15:0] data_in, input data_in_en, output reg [15:0]data_out, output data_out_en ); wire [15:0] line0; wire [15:0] line1; wire [15:0] line2;
reg [15:0] line0_data0; reg [15:0] line0_data1; reg [15:0] line0_data2;
reg [15:0] line1_data0; reg [15:0] line1_data1; reg [15:0] line1_data2;
reg [15:0] line2_data0; reg [15:0] line2_data1; reg [15:0] line2_data2;
reg data_out_en0; reg data_out_en1; reg data_out_en2; wire [18:0] result_data;
line3 line3x3_inst( .clken(data_in_en), .clock(clk), .shiftin(data_in), .shiftout(), .taps0x(line0), .taps1x(line1), .taps2x(line2) ); //---------------------------------------------------- // Form an image matrix of three multiplied by three //----------------------------------------------------
always @(posedge clk or negedge rst_n) begin if(!rst_n) begin line0_data0 <= 16'b0; line0_data1 <= 16'b0; line0_data2 <= 16'b0; line1_data0 <= 16'b0; line1_data1 <= 16'b0; line1_data2 <= 16'b0; line2_data0 <= 16'b0; line2_data1 <= 16'b0; line2_data2 <= 16'b0; data_out_en0 <= 1'b0; data_out_en1 <= 1'b0; data_out_en2 <= 1'b0; end else if(data_in_en) begin line0_data0 <= line0; line0_data1 <= line0_data0; line0_data2 <= line0_data1; line1_data0 <= line1; line1_data1 <= line1_data0; line1_data2 <= line1_data1; line2_data0 <= line2; line2_data1 <= line2_data0; line2_data2 <= line2_data1;
data_out_en0 <= data_in_en; data_out_en1 <= data_out_en0; data_out_en2 <= data_out_en1; end end
add_8 add_8( .clken(data_in_en), .clock(clk), .data0x(line0), .data1x(line0_data0), .data2x(line0_data1), .data3x(line1), .data4x(line1_data1), .data5x(line2), .data6x(line2_data0), .data7x(line2_data1), .result(result_data) );
always @(posedge clk or negedge rst_n) begin if(!rst_n) data_out <= 16'b0; else if(data_in_en) data_out <= result_data[18:3]; //data_out <= line2_data1; else ; end
endmodule
我们将lena的照片加入椒盐噪声,如下图:
然后生成coe文件,导入工程,下载后便可以看到滤波效果。
|