1、中值滤波算法作用
可以去除孤点噪声(适用于消除椒盐噪声(黑白噪声)),而且还可以保持图像的边缘特性,不会使图像产生显著的模糊。
2、算法原理
中值滤波算法简单来说就是:通过对33窗口中的数据进行排序,最终获得中值。
对于待处理的像素,我们选择一个33的窗口模板,该窗口内的像素为待处理像素的邻近像素,对窗口内的像素分别按行列排序,最终计算出中值,用该中值代替原像素值,实现中值滤波。
参考该博主的文章,这里不再赘述。
module filter_3x3(
input clk,
input rst_n,
input gray_de,
input [7:0] iData,
output filter_de, //生成窗口花费2clk,de信号延迟两拍
output reg [7:0] oData_11, oData_12, oData_13,
output reg [7:0] oData_21, oData_22, oData_23,
output reg [7:0] oData_31, oData_32, oData_33
);
endmodule
FPGA中无排序IP核,因此编写如下模块,每次排序直接例化调用即可。
sort模块:
module sort(
input clk,
input rst_n,
input [7:0] data1,
input [7:0] data2,
input [7:0] data3,
output reg [7:0] max,
output reg [7:0] mid,
output reg [7:0] min
);
//最大值
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
max <= 0;
else begin
if(data1 >= data2 && data1 >= data3)
max <= data1;
else if(data2 >= data1 && data2 >= data3)
max <= data2;
else
max <= data3;
end
end
//中间值
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
mid <= 0;
else begin
if((data1 >= data2 && data1 <= data3) || (data1 >= data3 && data1 <= data2))
mid <= data1;
else if((data2 >= data1 && data2 <= data3) || (data2 >= data3 && data2 <= data1))
mid <= data2;
else
mid <= data3;
end
end
//最小值
always @(posedge clk, negedge rst_n) begin
if(!rst_n)
min <= 0;
else begin
if(data1 <= data2 && data1 <= data3)
min <= data1;
else if(data2 <= data1 && data2 <= data3)
min <= data2;
else
min <= data3;
end
end
endmodule
module median_filter(
input clk,
input rst_n,
input wire iValid ,
input [7:0] filter_11,filter_12,filter_13, //生成的3*3窗口数据
input [7:0] filter_21,filter_22,filter_23,
input [7:0] filter_31,filter_32,filter_33,
output median_de ,//de同步信号
output [7:0] median_data // 最终中值
);
reg [3:0] de_shift1 ;
//第一行
wire [7:0] max_data1 ;
wire [7:0] mid_data1 ;
wire [7:0] min_data1 ;
//第二行
wire [7:0] max_data2 ;
wire [7:0] mid_data2 ;
wire [7:0] min_data2 ;
//第三行
wire [7:0] max_data3 ;
wire [7:0] mid_data3 ;
wire [7:0] min_data3 ;
//max-min,mid-mid,min-max
wire [7:0] max_min_data ;
wire [7:0] mid_mid_data ;
wire [7:0] min_max_data ;
//---------------------------------------------------
// 中值滤波
// 按行排序,共三行,例化三个模块
// 得到每行的最大、中间最小值
//---------------------------------------------------
//第一行
sort u1
(
.clk (clk ),
.rst_n (rst_n ),
.data1 (matrix_11 ),
.data2 (matrix_12 ),
.data3 (matrix_13 ),
.max (max_data1 ),
.mid (mid_data1 ),
.min (min_data1 )
);
//第二行
sort u2
(
.clk (clk ),
.rst_n (rst_n ),
.data1 (matrix_21 ),
.data2 (matrix_22 ),
.data3 (matrix_23 ),
.max (max_data2 ),
.mid (mid_data2 ),
.min (min_data2 )
);
//第三行
sort u3
(
.clk (clk ),
.rst_n (rst_n ),
.data1 (matrix_31 ),
.data2 (matrix_32 ),
.data3 (matrix_33 ),
.max (max_data3 ),
.mid (mid_data3 ),
.min (min_data3 )
);
//---------------------------------------------------
// 每一行排完后
// 取出第一列中的最小值
// 第二列的中间值
// 第三列的最大值
//---------------------------------------------------
//max-min
sort u4
(
.clk (clk ),
.rst_n (rst_n ),
.data1 (max_data1 ),
.data2 (max_data2 ),
.data3 (max_data3 ),
.max ( ),
.mid ( ),
.min (max_min_data )
);
//mid-mid
sort u5
(
.clk (clk ),
.rst_n (rst_n ),
.data1 (mid_data1 ),
.data2 (mid_data2 ),
.data3 (mid_data3 ),
.max ( ),
.mid (mid_mid_data ),
.min ( )
);
//min-max
sort u6
(
.clk (clk ),
.rst_n (rst_n ),
.data1 (min_data1 ),
.data2 (min_data2 ),
.data3 (min_data3 ),
.max (min_max_data ),
.mid ( ),
.min ( )
);
//---------------------------------------------------
// 得到最终中值mid_data
//---------------------------------------------------
sort u7
(
.clk (clk ),
.rst_n (rst_n ),
.data1 (max_min_data ),
.data2 (mid_mid_data ),
.data3 (min_max_data ),
.max ( ),
.mid (median_data ),
.min ( )
);
// 打拍做同步.3*3窗口花费1clk,中值滤波花费3clk
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
de_shift1 <= 4'b000;
end
else begin
de_shift1 <= {de_shift1[2:0], iValid};
end
end
assign median_de = de_shift1[3];
endmodule
以此时为例,对中值滤波进行验证。
中值滤波花费3clk,因此三个clk后输出计算值为30,与计算出来的对比正确。
clc;
clear all;
close all;
RGB = imread('flower.bmp');
imgn = imnoise(RGB,'salt & pepper',0.05); %加入椒盐噪声
gray = im2double(rgb2gray(imgn)); %灰度化
[ROW,COL, DIM] = size(gray);
%--------------------------------------------------------------------------
% Mean Filter 均值滤波
%--------------------------------------------------------------------------
Mean_Img = zeros(ROW,COL);
for r = 2:1:ROW-1
for c = 2:1:COL-1
Mean_Img(r,c) = (gray(r-1, c-1) + gray(r-1, c) + gray(r-1, c+1) + gray(r, c-1) + gray(r, c) + gray(r, c+1) + gray(r+1, c-1) + gray(r+1, c) + gray(r+1, c+1)) / 9;
end
end
%--------------------------------------------------------------------------
% Median Filter 中值滤波
%--------------------------------------------------------------------------
Median_Img = zeros(ROW,COL);
for r = 2:ROW-1
for c = 2:COL-1
median3x3 =[gray(r-1,c-1) gray(r-1,c) gray(r-1,c+1)
gray(r,c-1) gray(r,c) gray(r,c+1)
gray(r+1,c-1) gray(r+1,c) gray(r+1,c+1)];
sort1 = sort(median3x3, 2, 'descend');
sort2 = sort([sort1(1), sort1(4), sort1(7)], 'descend');
sort3 = sort([sort1(2), sort1(5), sort1(8)], 'descend');
sort4 = sort([sort1(3), sort1(6), sort1(9)], 'descend');
mid_num = sort([sort2(3), sort3(2), sort4(1)], 'descend');
Median_Img(r,c) = mid_num(2);
end
end
%--------------------------------------------------------------------------
% 图像显示
%--------------------------------------------------------------------------
subplot(2,2,1); imshow(imgn); title('椒盐噪声');
subplot(2,2,2); imshow(gray); title('含椒盐噪声的灰度图');
subplot(2,2,3); imshow(Mean_Img); title('均值滤波');
subplot(2,2,4); imshow(Median_Img); title('中值滤波');
%--------------------------------------------------------------------------
% 图像保存
%--------------------------------------------------------------------------
imwrite (gray,'含椒盐噪声的灰度图.bmp');
imwrite (Median_Img,'中值滤波.bmp');
由运行结果可知:中值滤波对椒盐噪声更有效,一次中值滤波后还存在少量椒盐噪声,可再次滤波,达到更好效果。均值滤波对椒盐噪声基本无作用。
可看到实现了椒盐噪声的去噪。
完整工程