1. 程式人生 > >基於FPGA的均值濾波算法的實現

基於FPGA的均值濾波算法的實現

微信訂閱號 lin ip核 灰度處理 ise mea view 調用 訂閱

  前面實現了基於FPGA的彩色圖像轉灰度處理,減小了圖像的體積,但是其中還是存在許多噪聲,會影響圖像的邊緣檢測,所以這一篇就要消除這些噪聲,基於灰度圖像進行圖像的濾波處理,為圖像的邊緣檢測做好夯實基礎。

  椒鹽噪聲(salt & pepper noise)是數字圖像的一個常見噪聲,所謂椒鹽,椒就是黑,鹽就是白,椒鹽噪聲就是在圖像上隨機出現黑色白色的像素。椒鹽噪聲是一種因為信號脈沖強度引起的噪聲,產生該噪聲的算法也比較簡單。

  均值濾波的方法將數據存儲成3x3的矩陣,然後求這個矩陣。在圖像上對目標像素給一個模板,該模板包括了其周圍的臨近像素(以目標象素為中心的周圍 8 個像素,構成一個濾波模板,即去掉目標像素本身),再用模板中的全體像素的平均值來代替原來像素值。

技術分享

  如圖所示,我們要進行均值濾波首先要生成一個3x3矩陣。算法運算窗口一般采用奇數點的鄰域來計算中值,最常用的窗口有3X3和5X5模型。下面介紹3X3窗口的Verilog實現方法。

  (1)通過2個或者3個RAM的存儲來實現3X3像素窗口;

  (2)通過2個或者3個FIFO的存儲來實現3X3像素窗口;

  (3)通過2行或者3行Shift_RAM的存儲來實現3X3像素窗口;

  要想用實現均值濾波和中值濾波,必須要先生成3x3陣列,在Altera系列裏,可以用QuatusII調用IP核——shift_RAM,具體設置參數如圖所示。

技術分享

  如上圖所示,其中shiftin是實時輸入的數據,taps1x,taps2x輸入數據的第二三行,當數據輸入成一行三個時,自動跳到下一行,最終形成每行是三列的一個矩陣,用均值濾波和中值濾波的處理方法即可,這樣基本是每一個目標都可以找到自己對應的一個3x3矩陣,最後進行處理。先進入IP核裏面的是最開始的的數據,所以在讀出的時候也是要放在第一行。

技術分享

  關於shift_ram的更詳細的解釋可以查看我的另一篇博文:http://www.cnblogs.com/ninghechuan/p/6789399.html。

  這學期做比賽用的是國產FPGA,開發軟件是PDS,這個軟件說實話比較簡潔,快,裏面也有shift_ram IP core,但是不能設置多行(一個IP只能存儲一行),不過只要你理解了shift_ram的工作的原理,完全可以用幾個來實現多行處理,我通過PDS開發套件調用兩個shift_register IP核來生成3X3矩陣實現3X3像素窗口。shift_register IP核可定義數據寬度、移位的行數、每行的深度。這裏我們需要8bit。640個數據每行,同事移位寄存2行即可。同時選擇時鐘使能端口clken。

技術分享

 1 shift_ram_end u_shift_ram_end1
 2      (
 3       .din       (row3_data),
 4       .clk       (shift_clk_en),
 5       .rst       (~rst_n),
 6       .dout      (row2_data)
 7      );
 8 
 9 shift_ram_end u_shift_ram_end2
10      (
11       .din       (row2_data),
12       .clk       (shift_clk_en),
13       .rst       (~rst_n),
14       .dout      (row1_data)
15      );

技術分享

  如圖所示,我們這裏將行設置為8,場設置為4,所以可以明顯的看到,當數據緩存到一行時,就會移位寄存到下一行,緩存兩行後便會生成3X3矩陣。

技術分享

  如圖所示,比較緩存的第一行的數據在3x3矩陣中,占第一行,結果相同,顯然是正確的。

技術分享

技術分享

  如圖所示,第二行、第三行和最終生成的3x3矩陣作比較,結果顯然是正確的。

技術分享
 1 //wire     [32:0]     matrix_row1 = {matrix_p11, matrix_p12,matrix_p13};//just for test
 2 //wire     [32:0]    matrix_row2 = {matrix_p21, matrix_p22,matrix_p23};
 3 //wire     [32:0]    matrix_row3 = {matrix_p31, matrix_p32,matrix_p33};
 4 always @(posedge clk or negedge rst_n)
 5 begin
 6     if(!rst_n)begin
 7            {matrix_p11, matrix_p12, matrix_p13}  <= 33h0;
 8          {matrix_p21, matrix_p22, matrix_p23} <= 33h0;
 9          {matrix_p31, matrix_p32, matrix_p33} <= 33h0;
10     end
11     else if(read_frame_href)begin
12         if(read_frame_clken)begin//shift_RAM data read clock enbale 
13             {matrix_p11, matrix_p12, matrix_p13} <= {matrix_p12, matrix_p13, row1_data};//1th shift input
14             {matrix_p21, matrix_p22, matrix_p23} <= {matrix_p22, matrix_p23, row2_data};//2th shift input 
15             {matrix_p31, matrix_p32, matrix_p33} <= {matrix_p32, matrix_p33, row3_data};//3th shift input 
16         end
17         else begin
18             {matrix_p11, matrix_p12, matrix_p13} <= {matrix_p11, matrix_p12, matrix_p13};
19             {matrix_p21, matrix_p22, matrix_p23} <= {matrix_p21, matrix_p22, matrix_p23};
20             {matrix_p31, matrix_p32, matrix_p33} <= {matrix_p31, matrix_p32, matrix_p33};
21             end
22     end
23     else begin
24            {matrix_p11, matrix_p12, matrix_p13}  <= 33h0;
25          {matrix_p21, matrix_p22, matrix_p23} <= 33h0;
26          {matrix_p31, matrix_p32, matrix_p33} <= 33h0;
27         end
28 end
3x3矩陣生成

技術分享

1 assign post_img_Y = mean_value4[10:3];//求平均值除以8,向右移位3位

  如圖所示,將3x3矩陣的中心像素的周圍八個點求和,我們上面還是采取了流水線的設計方法,來增加吞吐量,然後再求平均值代替目標像素的值,從波形圖上觀察,計算的結果顯然是正確的。這樣便完成了均值濾波的仿真。

技術分享
 1 //--------------------------------------------
 2 //Generate 8bit 3x3 matrix for video image processor
 3 //Image data has been processd
 4 wire             matrix_frame_vsync;    //Prepared Image data vsync valid signal
 5 wire             matrix_frame_href;    //Prepared Image data href vaild  signal
 6 wire             matrix_frame_clken;    //Prepared Image data output/capture enable clock
 7 wire     [7:0]     matrix_p11, matrix_p12, matrix_p13;//3x3 materix output 
 8 wire     [7:0]    matrix_p21, matrix_p22, matrix_p23;
 9 wire     [7:0]    matrix_p31, matrix_p32, matrix_p33;
10 
11 shift_RAM_3x3 u_shift_RAM_3x3
12 (
13     //global signals
14     .clk                                (clk),
15     .rst_n                                (rst_n),
16     //Image data prepred to be processd
17     .per_frame_vsync                    (per_frame_vsync),    //Prepared Image data vsync valid signal
18     .per_frame_href                        (per_frame_href),        //Prepared Image data href vaild  signal
19     .per_frame_clken                    (per_frame_clken),    //Prepared Image data output/capture enable clock
20     .per_img_Y                            (per_img_Y),            //Prepared Image brightness input
21 
22     //Image data has been processd
23     .matrix_frame_vsync                    (matrix_frame_vsync),    //Prepared Image data vsync valid signal
24     .matrix_frame_href                    (matrix_frame_href),    //Prepared Image data href vaild  signal
25     .matrix_frame_clken                    (matrix_frame_clken),    //Prepared Image data output/capture enable clock    
26     .matrix_p11                            (matrix_p11),
27     .matrix_p12                            (matrix_p12),
28     .matrix_p13                            (matrix_p13),    //3X3 Matrix output
29     .matrix_p21                            (matrix_p21),
30     .matrix_p22                            (matrix_p22),
31     .matrix_p23                            (matrix_p23),
32     .matrix_p31                            (matrix_p31),
33     .matrix_p32                            (matrix_p32),
34     .matrix_p33                            (matrix_p33)
35 
36 );
37 
38 //-----------------------------------------------------------------------
39 //step1
40 reg     [10:0]     mean_value1, mean_value2, mean_value3;
41 always @(posedge clk or negedge rst_n)
42 begin
43     if(!rst_n)begin
44         mean_value1 <= 11d0;
45         mean_value2 <= 11d0; 
46         mean_value3 <= 11d0;
47     end
48     else begin
49         mean_value1 <= matrix_p11 + matrix_p12 + matrix_p13;
50         mean_value2 <= matrix_p21 + 11d0 + matrix_p23;
51         mean_value3 <= matrix_p31 + matrix_p32 + matrix_p33;
52     end
53 end
54 
55 //step2
56 reg     [10:0]    mean_value4;
57 always @(posedge clk or negedge rst_n)
58 begin
59     if(!rst_n)
60         mean_value4 <= 11d0;
61     else
62         mean_value4 <= mean_value1 + mean_value2 + mean_value3;
63 end
對3x3矩陣求均值

  當然,最後為了保持時鐘的同步性,將消耗的時鐘延時輸出。

技術分享
 1 //------------------------------------------------------------
 2 //delay 2 clk
 3 reg     [1:0]     per_frame_clken_r;
 4 reg     [1:0]     per_frame_href_r;
 5 reg     [1:0]     per_frame_vsync_r;
 6 
 7 always @(posedge clk or negedge rst_n)
 8 begin
 9     if(!rst_n)begin
10         per_frame_clken_r <= 2b0;
11         per_frame_href_r <= 2b0;
12         per_frame_vsync_r <= 2b0;
13     end    
14     else begin
15         per_frame_clken_r <= {per_frame_clken_r[0], matrix_frame_clken};
16         per_frame_href_r <= {per_frame_href_r[0], matrix_frame_href};
17         per_frame_vsync_r <= {per_frame_vsync_r[0], matrix_frame_vsync};
18     end
19 end
20 
21 assign post_frame_vsync = per_frame_vsync_r[1];    
22 assign post_frame_href  = per_frame_href_r[1]; 
23 assign post_frame_clken = per_frame_clken_r[1];
保持時鐘的同步性

技術分享

技術分享

  圖上為灰度圖像,圖下為均值濾波後的圖像,可以看出濾波後的圖像有一些模糊,這是因為均值濾波就是將圖像做平滑處理,像素值高的像素會被拉低,像素值低像素會被拉高,趨向於一個平均值,所以圖像會變模糊一些。這樣基於FPGA的均值濾波就完成了,下一篇我會發布基於FPGA的中值濾波處理,並且比較這兩種濾波方式的優劣,最終選取較好的一種濾波方式進行圖像邊緣檢測處理。

技術分享

轉載請註明出處:NingHeChuan(寧河川)

個人微信訂閱號:NingHeChuan

如果你想及時收到個人撰寫的博文推送,可以掃描左邊二維碼(或者長按識別二維碼)關註個人微信訂閱號

知乎ID:NingHeChuan

微博ID:NingHeChuan

原文地址:http://www.cnblogs.com/ninghechuan/p/6984705.html

基於FPGA的均值濾波算法的實現