【博文连载】Median_Filter均值滤波算法的实现
ChinaAET《电子应用技术》出版过一篇值得参考的《基于FPGA的实时中值滤波器的硬件实现》,该文采用FPGA+SRAM实现了实时中值滤波,思维值得参考(当然Bingo认为实时实现仅用Shift_RAM就够用)。Okay,转移话题,我们现在的重点是如何快速求得9个值的均值,该论文介绍了某种快速排序法,如下图所示:
从图中可知,首先对,每行的3个像素进行排序,接着提取三个最大值中的最小值,最小值中的最大值,以及中值中的中值;最后再在得到的三个值中,提取中间值,得到最后的结果。整个计算耗费了3个clk,而不需要冒泡法去实现,时间上非常的节省。
在前面经过VIP_Matrix_Generate_3X3_8Bit模块的设计,花了九牛二虎之力,我们终于得到了梦想中的3*3像素阵列,每个像素为8Bit深度。此时开始设计实现均值滤波算法。
(1)首先分别对每行3个像素进行排序,Verilog HDL的实现,由于并行特性,我们只需要一个时钟,实现如下:
module Sort3
(
input clk,
input rst_n,
input [7:0] data1, data2, data3,
output reg [7:0] max_data, mid_data, min_data
);
//-----------------------------------
//Sort of 3 datas
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
max_data <= 0;
mid_data <= 0;
min_data <= 0;
end
else
begin
//get the max value
if(data1 >= data2 && data1 >= data3)
max_data <= data1;
else if(data2 >= data1 && data2 >= data3)
max_data <= data2;
else//(data3 >= data1 && data3 >= data2)
max_data <= data3;
//get the mid value
if((data1 >= data2 && data1 <= data3) || (data1 >= data3 && data1 <= data2))
mid_data <= data1;
else if((data2 >= data1 && data2 <= data3) || (data2 >= data3 && data2 <= data1))
mid_data <= data2;
else//((data3 >= data1 && data3 <= data2) || (data3 >= data2 && data3 <= data1))
mid_data <= data3;
//ge the min value
if(data1 <= data2 && data1 <= data3)
min_data <= data1;
else if(data2 <= data1 && data2 <= data3)
min_data <= data2;
else//(data3 <= data1 && data3 <= data2)
min_data <= data3;
end
end
上述电路实现了第一步的运算,新建Median_Filter_3X3.v,例化Sort3如下:
//Step1
wire [7:0] max_data1, mid_data1, min_data1;
Sort3 u_Sort3_1
(
.clk (clk),
.rst_n (rst_n),
.data1 (data11),
.data2 (data12),
.data3 (data13),
.max_data (max_data1),
.mid_data (mid_data1),
.min_data (min_data1)
);
(2)接着,对三行像素取得的排序进行处理,即提取三个最大值中的最小值,三个最小值中的最大值,以及三个中间值的中间值。这里直接例化Sort3模块即可,如下所示:
//Step2
wire [7:0] max_min_data, mid_mid_data, min_max_data;
Sort3 u_Sort3_4
(
.clk (clk),
.rst_n (rst_n),
.data1 (max_data1),
.data2 (max_data2),
.data3 (max_data3),
.max_data (),
.mid_data (),
.min_data (max_min_data)
);
Sort3 u_Sort3_5
(
.clk (clk),
.rst_n (rst_n),
.data1 (mid_data1),
.data2 (mid_data2),
.data3 (mid_data3),
.max_data (),
.mid_data (mid_mid_data),
.min_data ()
);
Sort3 u_Sort3_6
(
.clk (clk),
.rst_n (rst_n),
.data1 (min_data1),
.data2 (min_data2),
.data3 (min_data3),
.max_data (min_max_data),
.mid_data (),
.min_data ()
);
(3)最后,将(2)中得到的三个值,再次取中值,求得最终9个像素的中值,如下:
//step3
Sort3 u_Sort3_7
(
.clk (clk),
.rst_n (rst_n),
.data1 (max_min_data),
.data2 (mid_mid_data),
.data3 (min_max_data),
.max_data (),
.mid_data (target_data),
.min_data ()
);
Okay,从(1)-(3),我们花费了3个clock,完成了3*3像素阵列的中值提取。这三个步骤的RTL图如下所示,输入9个像素,输出目标中值像素:
最后在VIP_Gray_Median_Filter.v中的中值提取例化如下:
//Median Filter of 3X3 datas, need 3 clock
wire [7:0] mid_value;
Median_Filter_3X3 u_Median_Filter_3X3
(
.clk (clk),
.rst_n (rst_n),
//ROW1
.data11 (matrix_p11),
.data12 (matrix_p12),
.data13 (matrix_p13),
//ROW2
.data21 (matrix_p21),
.data22 (matrix_p22),
.data23 (matrix_p23),
//ROW3
.data31 (matrix_p31),
.data32 (matrix_p32),
.data33 (matrix_p33),
.target_data (mid_value)
);
既然耗费了3个时钟,那行场、像素使能也需要相应的移动3个时钟,来保持同步,这一点非常的重要,如下:
//------------------------------------------
//lag 3 clocks signal sync
reg [2:0] per_frame_vsync_r;
reg [2:0] per_frame_href_r;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
per_frame_vsync_r <= 0;
per_frame_href_r <= 0;
end
else
begin
per_frame_vsync_r <= {per_frame_vsync_r[1:0], matrix_frame_vsync};
per_frame_href_r <= {per_frame_href_r[1:0], matrix_frame_href};
end
end
assign post_frame_vsync = per_frame_vsync_r[2];
assign post_frame_href = per_frame_href_r[2];
assign post_img_Gray = post_frame_href ? mid_value : 8'd0;
最后,给出中值滤波的Modelsim仿真图,如下图所示(新架构没有*_clken):
在前面已经搞定3*3的基础上,实现个中值滤波已经非常轻松了,当然前提是您已经掌握了这些设计内容。在VIP_Image_Processor中例化VIP_Gray_Median_Filter,如下所示:
//--------------------------------------
//Gray Image median filter for better picture quality.
wire post3_frame_vsync; //Processed Image data vsync valid signal
wire post3_frame_href; //Processed Image data href vaild signal
wire [7:0] post3_img_Gray; //Processed Image Gray output
VIP_Gray_Median_Filter
#(
.IMG_HDISP (IMG_HDISP), //640*480
.IMG_VDISP (IMG_VDISP)
)
u_VIP_Gray_Median_Filter
(
//global clock
.clk (clk), //cmos video pixel clock
.rst_n (rst_n), //global reset
//Image data prepred to be processd
.per_frame_vsync (post2_frame_vsync), //Prepared Image data vsync valid signal
.per_frame_href (post2_frame_href), //Prepared Image data href vaild signal
.per_img_Gray (post2_img_Gray), //Prepared Image brightness input
//Image data has been processd
.post_frame_vsync (post3_frame_vsync), //Processed Image data vsync valid signal
.post_frame_href (post3_frame_href), //Processed Image data href vaild signal
.post_img_Gray (post3_img_Gray) //Processed Image brightness output
);
`else
assign post3_frame_vsync = post2_frame_vsync;
assign post3_frame_href = post2_frame_href;
assign post3_img_Gray = post2_img_Gray;
最后,全编译、生成下载jic文件,在VGA或者PC上位机上观察处理后的视频,如下所示:
上图左为原始灰度图像,上图右为中值滤波后的图像,可见中值滤波后的图像相对暗了一点,因为最大值被舍去了。但相对于均值滤波而言,中值滤波在滤除噪声的基础上,有效的保存了细节。
此外,顺便说说均值滤波和中值滤波的效果区别,这里对比一下如下图:
上图左为均值滤波图像,上图右为中值滤波后的图像。从图分析,可见均值滤波后的图像,较中值滤波处理的图像,模糊而又丧失了细节。对于椒盐噪声类的处理,中值滤波的优势要比均值滤波大。
此正如前面说的,图像处理中滤波算法有很多,但是万变不离其宗,掌握了最基本的图像处理,更多的模板算法处理方式,也就是移植与实现的问题。Bingo在此介绍了最基本的中值滤波算法的FPGA实现,更典型、富有针对性、更NB的滤波算法,有待读者自己去研究实现!
VIP图像处理,让世界变得更精彩!
郑重声明:只有100%掌握了这一章,才能了解Bingo VIP算法实现的精髓,才有继续往下看的意义!!!