中值滤波的目的是滤除椒盐噪声,就是那种像是在图像上撒了盐粒子一样玩意儿。这一篇就来谈谈如何在FPGA上实现中值滤波。
数字滤波器的设计其实就是模板的设计。
本实验选取3x3模板,中值滤波也很简单,求模板上三行三列像素值的中值就可以了。
那么,如何求中值呢?
先看一下 RTL Viewer:
1)第一步 搭建LineBuffer
搭建LineBuffer方法,已经在上篇博客 “图像高斯滤波的FPGA实现--实时高速” 中详细介绍,目的和原理完全相同。读者可参阅上篇。
2)第二步 搭建三个移位寄存器
因为LineBuffer只是提供了三根管子,输出的是每根管子的末尾像素值,只有三个。但我们需要3x3=9个像素值,所以需要在每根管子的后面加上2个D触发器,目的是延时得到各行的其余两个像素!!
D触发器的程序如下;
module D_FF
(
clk,
d,
q
);
input clk;
input [4:0]d;
output reg [4:0]q;
always@(posedge clk)
q <= d;
endmodule
很简单吧~
3)第三步 得到了3x3个像素之后,就需要把这9个像素值的中值提取出来,方法如下:
如下图:
First:先将每行元素按从大到小排列,得到右方的九宫格
Second:求
最大值列(第1列)的最小值:Min_of_Max、
中值列(第1列)的中值:Med_of_Med、
最小值列(第1列)的最大值:Max_of_Min、
Third:求Min_of_Max、Med_of_Med、Max_of_Min这三者的中值,得到Med_of_Nine即为9个像素的全体中值! 完毕
效果图如下,前一张是未经中值滤波的边缘提取,后一张是经过中值滤波的边缘提取。 可以明显看出,滤波去噪后的边缘提取图干净了许多!
原理说完了,下面贴上第三步的Verilog HDL源码
module MedianSeletor
(
input iCLK,
input iRST_N,
input [4:0] Data1,
input [4:0] Data2,
input [4:0] Data3,
input [4:0] Data4,
input [4:0] Data5,
input [4:0] Data6,
input [4:0] Data7,
input [4:0] Data8,
input [4:0] Data9,
output reg [4:0] Median //3行3列全体中值
);
reg [4:0]Max1;
reg [4:0]Max2;
reg [4:0]Max3;
reg [4:0]Med1;
reg [4:0]Med2;
reg [4:0]Med3;
reg [4:0]Min1;
reg [4:0]Min2;
reg [4:0]Min3;
reg [4:0]Min_of_Max;
reg [4:0]Med_of_Med;
reg [4:0]Max_of_Min;
always@(negedge iRST_N or posedge iCLK)
if(!iRST_N)
begin
Max1 <= 5'd0;
Max2 <= 5'd0;
Max3 <= 5'd0;
Med1 <= 5'd0;
Med2 <= 5'd0;
Med3 <= 5'd0;
Min1 <= 5'd0;
Min2 <= 5'd0;
Min3 <= 5'd0;
Min_of_Max <= 5'd0;
Med_of_Med <= 5'd0;
Max_of_Min <= 5'd0;
Median <= 5'd0;
end
else
begin
//找到各行最大值
//第一行
if(Data1 >= Data2 && Data1 >= Data3)
Max1 <= Data1;
else if(Data2 >= Data1 && Data2 >= Data3)
Max1 <= Data2;
else if(Data3 >= Data1 && Data3 >= Data2)
Max1 <= Data3;
//第二行
if(Data4 >= Data5 && Data4 >= Data6)
Max2 <= Data4;
else if(Data5 >= Data4 && Data5 >= Data6)
Max2 <= Data5;
else if(Data6 >= Data4 && Data6 >= Data5)
Max2 <= Data6;
//第三行
if(Data7 >= Data8 && Data7 >= Data9)
Max3 <= Data7;
else if(Data8 >= Data7 && Data8 >= Data9)
Max3 <= Data8;
else if(Data9 >= Data7 && Data9 >= Data8)
Max3 <= Data9;
//找到各行中值
//第一行
if((Data1 >= Data2 && Data1 <= Data3) || (Data1 >= Data3 && Data1 <= Data2))
Med1 <= Data1;
else if((Data2 >= Data1 && Data2 <= Data3) || (Data2 >= Data3 && Data2 <= Data1))
Med1 <= Data2;
else if((Data3 >= Data1 && Data3 <= Data2) || (Data3 >= Data2 && Data3 <= Data1))
Med1 <= Data3;
//第二行
if((Data4 >= Data5 && Data4 <= Data6) || (Data4 >= Data6 && Data4 <= Data5))
Med2 <= Data4;
else if((Data5 >= Data4 && Data5 <= Data6) || (Data5 >= Data6 && Data5 <= Data4))
Med2 <= Data5;
else if((Data6 >= Data4 && Data6 <= Data5) || (Data6 >= Data5 && Data6 <= Data4))
Med2 <= Data6;
//第三行
if((Data7 >= Data8 && Data7 <= Data9) || (Data7 >= Data9 && Data7 <= Data8))
Med3 <= Data7;
else if((Data8 >= Data7 && Data8 <= Data9) || (Data8 >= Data9 && Data8 <= Data7))
Med3 <= Data8;
else if((Data9 >= Data7 && Data9 <= Data8) || (Data9 >= Data8 && Data9 <= Data7))
Med3 <= Data9;
//找到各行最小值
//第一行
if(Data1 <= Data2 && Data1 <= Data3)
Min1 <= Data1;
else if(Data2 <= Data1 && Data2 <= Data3)
Min1 <= Data2;
else if(Data3 <= Data1 && Data3 <= Data2)
Min1 <= Data3;
//第二行
if(Data4 <= Data5 && Data4 <= Data6)
Min2 <= Data4;
else if(Data5 <= Data4 && Data5 <= Data6)
Min2 <= Data5;
else if(Data6 <= Data4 && Data6 <= Data5)
Min2 <= Data6;
//第三行
if(Data7 <= Data8 && Data7 <= Data9)
Min3 <= Data7;
else if(Data8 <= Data7 && Data8 <= Data9)
Min3 <= Data8;
else if(Data9 <= Data7 && Data9 <= Data8)
Min3 <= Data9;
//找到最大值列的最小值
if(Max1 <= Max2 && Max1 <= Max3)
Min_of_Max <= Max1;
else if(Max2 <= Max1 && Max2 <= Max3)
Min_of_Max <= Max2;
else if(Max3 <= Max1 && Max3 <= Max2)
Min_of_Max <= Max3;
//找到中值列的中值
if((Med1 >= Med2 && Med1 <= Med3) || (Med1 >= Med3 && Med1 <= Med2))
Med_of_Med <= Med1;
else if((Med2 >= Med1 && Med2 <= Med3) || (Med2 >= Med3 && Med2 <= Med1))
Med_of_Med <= Med2;
else if((Med3 >= Med1 && Med3 <= Med2) || (Med3 >= Med2 && Med3 <= Med1))
Med_of_Med <= Med3;
//找到最小值列的最大值
if(Min1 >= Min2 && Min1 >= Min3)
Max_of_Min <= Min1;
else if(Min2 >= Min1 && Min2 >= Min3)
Max_of_Min <= Min2;
else if(Min3 >= Min1 && Min3 >= Min2)
Max_of_Min <= Min3;
//找到三行三列的全体中值
if((Min_of_Max >= Med_of_Med && Min_of_Max <= Max_of_Min) || (Min_of_Max >= Max_of_Min && Min_of_Max <= Med_of_Med))
Median <= Min_of_Max;
else if((Med_of_Med >= Min_of_Max && Med_of_Med <= Max_of_Min) || (Med_of_Med >= Max_of_Min && Med_of_Med <= Min_of_Max))
Median <= Med_of_Med;
else if((Max_of_Min >= Min_of_Max && Max_of_Min <= Med_of_Med) || (Max_of_Min >= Med_of_Med && Max_of_Min <= Min_of_Max))
Median <= Max_of_Min;
end
endmodule