1. 背景知识
均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标像素为中心的周围 8 个像素,构成一个滤波模板,即去掉目了其周围的临近像素(以目标像素为中心的周围 8 个像素,构成一个滤波模板,即去掉目标像素本身),再用模板中的全体像素的平均值来代替原来像素值。
均值滤波也称为线性滤波,其采用的主要方法为邻域平均法。线性滤波的基本原理是用均值代替原图像中的各个像素值,即对待处理的当前像素点(x,y),选择一个模板,该模
板由其近邻的若干像素组成,求模板中所有像素的均值,再把该均值赋予当前像素点(x,y),作为处理后图像在该点上的灰度 g(x,y),即 g(x,y)=1/m ∑f(x,y) m 为该模板中包含当前像素在内的像素总个数。
均值滤波本身存在着固有的缺陷,即它不能很好地保护图像细节,在图像去噪的同时也
破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点。
2. FPGA 的均值滤波算法实现步骤
(x-1,y-1) (x,y-1) (x+1,y-1)
(x-1,y) (x,y) (x+1,y)
(x-1,y+1) (x,y+1) (x+1,y+1)
3x3 像素坐标位置
中心点(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>求周围邻域八个点的像素值之和
3>将结果右移三位(相当于除以 8)得到结果。
`timescale1ns/1ps////Company: //Engineer: ////CreateDate: 2019/05/0618:31:28//DesignName: //ModuleName: ram_3x3_8bit//ProjectName: //TargetDevices: //ToolVersions: //Description: ////Dependencies: ////Revision: //Revision0.01-FileCreated//AdditionalComments: ////moduleram_3x3_8bit( clk, rst_n, per_clken, per_img, matrix_clken, matrix_p11, matrix_p12, matrix_p13, matrix_p21, matrix_p22, matrix_p23, matrix_p31, matrix_p32, matrix_p33 ); inputclk; inputrst_n; inputper_clken;//PreparedImagedataoutput/captureenableclockinput [7:0] per_img;//PreparedImagebrightnessinputoutputmatrix_clken;//PreparedImagedataoutput/captureenableclockoutputreg [7:0] matrix_p11; outputreg [7:0] matrix_p12; outputreg [7:0] matrix_p13; //3X3Matrixoutputoutputreg [7:0] matrix_p21; outputreg [7:0] matrix_p22; outputreg [7:0] matrix_p23; outputreg [7:0] matrix_p31; outputreg [7:0] matrix_p32; outputreg [7:0] matrix_p33; wire [7:0] row1_data; wire [7:0] row2_data; reg [7:0] row3_data; always@(posedgeclkornegedgerst_n)beginif(rst_n==1'b0)beginrow3_data<=1'b0;endelseif(per_clken==1'b1)beginrow3_data<=per_img; endelsebeginrow3_data<=row3_data; endendwireshift_clk_en=per_clken; c_shift_ram_0uut1_Shift_RAM( .D(row3_data), //inputwire [7 : 0] D .CLK(shift_clk_en), //inputwireCLK .SCLR(~rst_n), //inputwireSCLR .Q(row2_data) //outputwire [7 : 0] Q ); c_shift_ram_0uut2_Shift_RAM( .D(row2_data), //inputwire [7 : 0] D .CLK(shift_clk_en), //inputwireCLK .SCLR(~rst_n), //inputwireSCLR .Q(row1_data) //outputwire [7 : 0] Q ); //每个像素使能延时三个时钟周期delay3clkreg [1:0] per_clken_r; always@(posedgeclkornegedgerst_n)beginif(rst_n==1'b0)beginper_clken_r<=1'b0;endelsebeginper_clken_r<= {per_clken_r[0], per_clken}; endendwireread_clken=per_clken_r[0]; assignmatrix_clken=per_clken_r[1]; always@(posedgeclkornegedgerst_n)beginif(rst_n==1'b0)begin {matrix_p11, matrix_p12, matrix_p13} <=1'b0; {matrix_p21, matrix_p22, matrix_p23} <=1'b0; {matrix_p31, matrix_p32, matrix_p33} <=1'b0;endelseif(read_clken==1'b1)begin {matrix_p11, matrix_p12, matrix_p13} <= {matrix_p12, matrix_p13, row1_data}; {matrix_p21, matrix_p22, matrix_p23} <= {matrix_p22, matrix_p23, row2_data}; {matrix_p31, matrix_p32, matrix_p33} <= {matrix_p32, matrix_p33, row3_data}; endelsebegin {matrix_p11, matrix_p12, matrix_p13} <= {matrix_p11, matrix_p12, matrix_p13}; {matrix_p21, matrix_p22, matrix_p23} <= {matrix_p21, matrix_p22, matrix_p23}; {matrix_p31, matrix_p32, matrix_p33} <= {matrix_p31, matrix_p32, matrix_p33}; endendendmodule