FPGA丨中值滤波算法实现
參考:小梅哥的《FPGA系統設計與驗證實戰指南》
一、算法介紹
中值濾波法是一種非線性平滑技術,它將每一像素點的灰度值設置為該點某鄰域窗口內的所有像素點灰度值的中值.
中值濾波是基于排序統計理論的一種能有效抑制噪聲的非線性信號處理技術,中值濾波的基本原理是把數字圖像或數字序列中一點的值用該點的一個鄰域中各點值的中值代替,讓周圍的像素值接近的真實值,從而消除孤立的噪聲點。方法是用某種結構的二維滑動模板,將板內像素按照像素值的大小進行排序,生成單調上升(或下降)的為二維數據序列。二維中值濾波輸出為g(x,y)=med{f(x-k,y-l),(k,l∈W)} ,其中,f(x,y),g(x,y)分別為原始圖像和處理后圖像。W 為二維模板,通常為 33,55 區域,也可以是不同的的形狀,如線狀,圓形,十字形,圓環形等。
中值濾波法對消除椒鹽噪聲非常有效,在光學測量條紋圖象的相位分析處理方法中有特殊作用,但在條紋中心分析方法中作用不大。中值濾波在圖像處理中,常用于保護邊緣信息,是經典的平滑噪聲的方法。
要得到模板中數據的中間值,首先要將數據按大小排序,然后根據有序的數字序列來找中問值。中值濾波排序的過程有很多成熟的算法,如冒泡排序、二分排序等,大多是基于微機平臺的軟件算法,而適合硬件平臺的排序算法則比較少。
FPGA 中值濾波實現方法:
(摘自:https://blog.csdn.net/Laplace666/article/details/83826443)
中值濾波方法是,對待處理的當前像素,選擇一個模板,該模板為其鄰近的若干個像素組成,對模板的像素由小到大進行排序,再用模板的中值來替代原像素的值的方法。
當我們使用3x3窗口后獲取鄰域中的9個像素,就需要對9個像素值進行排序,為了提高排序效率,排序算法思想如下圖所示:
(1) 對窗內的每行像素按降序排序,得到最大值、中間值和最小值;
(2) 把三行的最小值相比較,取其中的最大值;
(3) 把三行的最大值相比較,取其中的最小值;
(4) 把三行的中間值相比較,再取一次中間值;
(5) 把前面得到的三個值再做一次排序,獲得的中值即該窗口的中值。
二、程序設計
關于如何形成3*3的像素矩陣,參考另一篇文章:FPGA丨設計行緩存(linebuffer)對圖像開窗
timescale 1ns/1ps module median_filtering(input clk,input rst_n,input [15:0] data_in,input data_in_en,input hs_in,input vs_in,output[15:0] data_out,output data_out_en,output hs_out,output vs_out);wire [15:0] line0; wire [15:0] line1; wire [15:0] line2; //-------------------------------------- //pipeline control signal //-------------------------------------- reg hs0; reg hs1; reg hs2; reg vs0; reg vs1; reg vs2; reg de0; reg de1; reg de2; //------------------------------------- //pipeline data 對應3*3窗口內的九個像素 //------------------------------------- reg [15:0] line0_data0; reg [15:0] line0_data1; reg [15:0] line0_data2;reg [15:0] line1_data0; reg [15:0] line1_data1; reg [15:0] line1_data2;reg [15:0] line2_data0; reg [15:0] line2_data1; reg [15:0] line2_data2; //-------------------------------------- //define line max mid min //-------------------------------------- reg [15:0] line0_max; reg [15:0] line0_mid; reg [15:0] line0_min;reg [15:0] line1_max; reg [15:0] line1_mid; reg [15:0] line1_min;reg [15:0] line2_max; reg [15:0] line2_mid; reg [15:0] line2_min; //---------------------------------------------------------------- // define //max of min //mid of mid// min of max //--------------------------------------------------------------- reg [15:0] max_max; reg [15:0] max_mid; reg [15:0] max_min;reg [15:0] mid_max; reg [15:0] mid_mid; reg [15:0] mid_min;reg [15:0] min_max; reg [15:0] min_mid; reg [15:0] min_min; //--------------------------------------------- // define mid of mid //--------------------------------------------- reg [15:0] mid; line3x3 line3x3_inst(.clken(data_in_en),.clock(clk),.shiftin(data_in),.shiftout(),.taps0x(line0),.taps1x(line1),.taps2x(line2)); //---------------------------------------------------- //delay control signal //---------------------------------------------------- always @(posedge clk or negedge rst_n) beginif(!rst_n) beginhs0 <= 1'b0;hs1 <= 1'b0;hs2 <= 1'b0;vs0 <= 1'b0;vs1 <= 1'b0;vs2 <= 1'b0;de0 <= 1'b0;de1 <= 1'b0;de2 <= 1'b0;endelse if(data_in_en) beginhs0 <= hs_in;hs1 <= hs0;hs2 <= hs1;vs0 <= vs_in;vs1 <= vs0;vs2 <= vs1;de0 <= data_in_en;de1 <= de0;de2 <= de1; end end //-------------------------------------------------------------------- // Form an image matrix of three multiplied by three //-------------------------------------------------------------------- always @(posedge clk or negedge rst_n) beginif(!rst_n) beginline0_data0 <= 16'b0;line0_data1 <= 16'b0;line0_data2 <= 16'b0;line1_data0 <= 16'b0;line1_data1 <= 16'b0;line1_data2 <= 16'b0;line2_data0 <= 16'b0;line2_data1 <= 16'b0;line2_data2 <= 16'b0;endelse if(data_in_en) beginline0_data0 <= line0;line0_data1 <= line0_data0;line0_data2 <= line0_data1;line1_data0 <= line1;line1_data1 <= line1_data0;line1_data2 <= line1_data1;line2_data0 <= line2;line2_data1 <= line2_data0;line2_data2 <= line2_data1; endelse ; end //-------------------------------------------------------------------------- //(line0 line1 line2) of (max mid min) //-------------------------------------------------------------------------- always @(posedge clk or negedge rst_n) beginif(!rst_n) beginline0_max <= 16'd0;line0_mid <= 16'd0;line0_min <= 16'd0;endelse if(data_in_en) beginif((line0_data0 >= line0_data1) && (line0_data0 >= line0_data2)) beginline0_max <= line0_data0;if(line0_data1 >= line0_data2) beginline0_mid <= line0_data1;line0_min <= line0_data2;endelse beginline0_mid <= line0_data2;line0_min <= line0_data1;endendelse if((line0_data1 > line0_data0) && (line0_data1 >= line0_data2)) beginline0_max <= line0_data1;if(line0_data0 >= line0_data2) beginline0_mid <= line0_data0;line0_min <= line0_data2;endelse beginline0_mid <= line0_data2;line0_min <= line0_data0;endendelse if((line0_data2 > line0_data0) && (line0_data2 > line0_data1)) beginline0_max <= line0_data2;if(line0_data0 >= line0_data1) beginline0_mid <= line0_data0;line0_min <= line0_data1;endelse beginline0_mid <= line0_data1;line0_min <= line0_data0;endendend end always @(posedge clk or negedge rst_n) beginif(!rst_n) beginline1_max <= 16'd0;line1_mid <= 16'd0;line1_min <= 16'd0;endelse if(data_in_en) beginif((line1_data0 >= line1_data1) && (line1_data0 >= line1_data2)) beginline1_max <= line1_data0;if(line1_data1 >= line1_data2) beginline1_mid <= line1_data1;line1_min <= line1_data2;endelse beginline1_mid <= line1_data2;line1_min <= line1_data1;endendelse if((line1_data1 > line1_data0) && (line1_data1 >= line1_data2)) beginline1_max <= line1_data1;if(line1_data0 >= line1_data2) beginline1_mid <= line1_data0;line1_min <= line1_data2;endelse beginline1_mid <= line1_data2;line1_min <= line1_data0;end endelse if((line1_data2 > line1_data0) && (line1_data2 > line1_data1)) beginline1_max <= line1_data2;if(line1_data0 >= line1_data1) beginline1_mid <= line1_data0;line1_min <= line1_data1;endelse beginline1_mid <= line1_data1;line1_min <= line1_data0;end endend end always @(posedge clk or negedge rst_n) beginif(!rst_n) beginline2_max <= 16'd0;line2_mid <= 16'd0;line2_min <= 16'd0;endelse if(data_in_en) beginif((line2_data0 >= line2_data1) && (line2_data0 >= line2_data2)) beginline2_max <= line2_data0;if(line2_data1 > line2_data2) beginline2_mid <= line2_data1;line2_min <= line2_data2;endelse beginline2_mid <= line2_data2;line2_min <= line2_data1;endendelse if((line2_data1 > line2_data0) && (line2_data1 >= line2_data2)) beginline2_max <= line2_data1;if(line2_data0 >= line2_data2) beginline2_mid <= line2_data0;line2_min <= line2_data2;endelse beginline2_mid <= line2_data2;line2_min <= line2_data0;end endelse if((line2_data2 > line2_data0) && (line2_data2 > line2_data1)) beginline2_max <= line2_data2;if(line2_data0 >= line2_data1) beginline2_mid <= line2_data0;line2_min <= line2_data1;endelse beginline2_mid <= line2_data1;line2_min <= line2_data0;end endend end //-------------------------------------------------------------------------- // (max_max max_mid max_min) of ((line0 line1 line2) of max) //-------------------------------------------------------------------------- always @(posedge clk or negedge rst_n) beginif(!rst_n) beginmax_max <= 16'd0;max_mid <= 16'd0;max_min <= 16'd0;endelse if(data_in_en) beginif((line0_max >= line1_max) && (line0_max >= line2_max)) beginmax_max <= line0_max;if(line1_max >= line2_max) beginmax_mid <= line1_max;max_min <= line2_max;endelse beginmax_mid <= line2_max;max_min <= line1_max;endendelse if((line1_max > line0_max) && (line1_max >= line2_max)) beginmax_max <= line1_max;if(line0_max >= line2_max) beginmax_mid <= line0_max;max_min <= line2_max;endelse beginmax_mid <= line2_max;max_min <= line0_max;endendelse if((line2_max > line0_max) && (line2_max > line1_max)) beginmax_max <= line2_max;if(line0_max >= line1_max) beginmax_mid <= line0_max;max_min <= line1_max;endelse beginmax_mid <= line1_max;max_min <= line0_max;endendend end //-------------------------------------------------------------------------- // (mid_max mid_mid mid_min) of ((line0 line1 line2)of mid) //-------------------------------------------------------------------------- always @(posedge clk or negedge rst_n) beginif(!rst_n) beginmid_max <= 16'd0;mid_mid <= 16'd0;mid_min <= 16'd0;endelse if(data_in_en) beginif((line0_mid >= line1_mid) && (line0_mid >= line2_mid)) beginmid_max <= line0_mid;if(line1_mid >= line2_mid) beginmid_mid <= line1_mid;mid_min <= line2_mid;endelse beginmid_mid <= line2_mid;mid_min <= line1_mid;endendelse if((line1_mid > line0_mid) && (line1_mid >= line2_mid)) beginmid_mid <= line1_mid;if(line0_mid >= line2_mid) beginmid_mid <= line0_mid;mid_min <= line2_mid;endelse beginmid_mid <= line2_mid;mid_min <= line0_mid;endendelse if((line2_mid > line0_mid) && (line2_mid > line1_mid)) beginmid_max <= line2_mid;if(line0_mid >= line1_mid) beginmid_mid <= line0_mid;mid_min <= line1_mid;endelse beginmid_mid <= line1_mid;mid_min <= line0_mid;endendend end //-------------------------------------------------------------------------- // (min_max min_mid min_min) of ((line0 line1 line2)of min) //-------------------------------------------------------------------------- always @(posedge clk or negedge rst_n) beginif(!rst_n) beginmin_max <= 16'd0;min_mid <= 16'd0;min_min <= 16'd0;endelse if(data_in_en) beginif((line0_min >= line1_min) && (line0_min >= line2_min)) beginmin_max <= line0_min;if(line1_min >= line2_min) beginmin_mid <= line1_min;min_min <= line2_min;endelse beginmin_mid <= line2_min;min_min <= line1_min;endendelse if((line1_min > line0_min) && (line1_min >= line2_min)) beginmin_max <= line1_min;if(line0_min >= line2_min) beginmin_mid <= line0_min;min_min <= line2_min;endelse beginmin_mid <= line2_min;min_min <= line0_min;endendelse if((line2_min > line0_min) && (line2_min > line1_min)) beginmin_max <= line2_min;if(line0_min >= line1_min) beginmin_mid <= line0_min;min_min <= line1_min;endelse beginmin_mid <= line1_min;min_min <= line0_min;endendend end //-------------------------------------------------------------------------- // middle //-------------------------------------------------------------------------- always @(posedge clk or negedge rst_n) beginif(!rst_n)mid <= 16'd0;else if(data_in_en) beginif(((max_min >= mid_mid) && (max_min < min_max)) || ((max_min >= min_max) && (max_mid < mid_mid)))mid <= max_min ;else if(((mid_mid > max_min ) && (mid_mid < min_max)) || ((min_mid >= min_max) && (mid_mid < max_min )))mid <= mid_mid;else if(((min_max> max_min ) && (min_max< mid_mid)) || ((min_max> mid_mid) && (mid_min < max_min )))mid <= min_max;endelse ; end //-------------------------------------------------------------------------- //result //-------------------------------------------------------------------------- assign data_out = mid; assign data_out_en = de2; assign hs_out = hs2; assign vs_out = vs2; endmodule需要注意的是:
上述代碼的輸入圖像數據默認是灰度圖像的數據,數據位寬為16。關于如何得到灰度圖,可以參考另一篇文章:
FPGA丨RGB轉Gray算法實現(rgb2ycbcr)
總結
以上是生活随笔為你收集整理的FPGA丨中值滤波算法实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学会System Generator(1
- 下一篇: 小涴熊漫画CMS一款不错的开源免费的漫画