1. 背景知识
均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括
了其周围的临近像素(以目标像素为中心的周围 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)得到结果。
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2019/05/08 20:27:48
// Design Name:
// Module Name: Mean_filter
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module Mean_filter(
clk,
rst_n,
img_i,
clken_i,
img_o,
clken_o,
ram_addr
);
input clk;
input rst_n;
input [7:0]img_i;
input clken_i;
output [7:0]img_o;
output clken_o;
output reg [15:0]ram_addr;
//产生3x3阵列
wire [7:0] matrix_p11, matrix_p12, matrix_p13;//3x3
wire [7:0] matrix_p21, matrix_p22, matrix_p23;
wire [7:0] matrix_p31, matrix_p32, matrix_p33;
wire matrix_clken;
ram_3x3_8bit uut_ram_3x3_8bit(
.clk(clk),
.rst_n(rst_n),
.per_clken(clken_i),
.per_img(img_i),
.matrix_clken(matrix_clken),
.matrix_p11(matrix_p11),
.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)
);
//这里流水处理首先把每个行的相加 -1
reg [10:0] mean_val_1,mean_val_2, mean_val_3;
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
mean_val_1<=0;
mean_val_2<=0;
mean_val_3<=0;
end
else begin
mean_val_1<= matrix_p11 + matrix_p12 + matrix_p13;
mean_val_2<= matrix_p21 + 11'd0 + matrix_p23;
mean_val_3<= matrix_p31 + matrix_p32 + matrix_p33;
end
end
//然后相加 -2
reg [10:0] sum_mean;
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
sum_mean<=1'b0;
end
else begin
sum_mean<= mean_val_1 + mean_val_2 + mean_val_3;
end
end
//二级流水线打拍 打2拍
reg [1:0] per_clken_r;
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
per_clken_r <= 2'b0;
end
else begin
per_clken_r <= {per_clken_r[0], matrix_clken};
end
end
assign clken_o = per_clken_r[1];
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
ram_addr<=1'b0;
end
else if(clken_o== 1'b1)begin
ram_addr<=ram_addr+1'b1;
end
else begin
ram_addr<=ram_addr;
end
end
assign img_o =sum_mean[10:3];
endmodule