基於FPGA灰度圖像高斯濾波算法的實現

基於FPGA灰度圖像高斯濾波算法的實現

1.內容概要

高斯濾波是一種線性平滑濾波,適用於消除高斯噪聲,廣泛應用於圖像處理的減噪過程。通俗的講,高斯濾波就是對整幅圖像進行加權平均的過程,每一個像素點的值,都由其本身和鄰域內的其他像素值經過加權平均後得到。高斯濾波的具體操作是:用一個模板(或稱卷積、掩模)掃描圖像中的每一個像素,用模板確定的鄰域內像素的加權平均灰度值去替代模板中心像素點的值。
一位高斯分佈:
在這裏插入圖片描述
二位高斯分佈:
在這裏插入圖片描述
高斯濾波後圖像被平滑的程度取決於標準差。它的輸出是臨域像素的加權平均,同時離中心越近的像素權重越高。因此,相對於均值濾波(mean filter)它的平滑效果更柔和,而且邊緣保留的也更好。
高斯濾波被用作爲平滑濾波器的本質原因是因爲它是一個低通濾波器,而且大部份基於卷積平滑濾波器都是低通濾波器。
GAUSS 濾波算法克服了邊界效應,因而濾波後的圖像較好。

2.高斯濾波算法實現步驟

1 4 7 4 1
4 16 26 16 4
7 26 41 26 7
4 16 26 16 4
1 4 7 4 1

(1/273) *

高斯濾波5x5算子
1 2 1
2 4 2
1 2 1

(1/16)*

高斯濾波3x3算子

1>串行像素形成3x3矩陣

(x-1,y-1) (x,y-1) (x+1,y-1)
(x-1,y) (x,y) (x+1,y)
(x-1,y+1) (x,y+1) (x+1,y+1)

f(x,y)表示(x,y)點的像素值;
g(x,y)表示(x,y)點經過高斯濾波處理後的值;

2>用模板確定的鄰域內像素的加權平均灰度值去替代模板中心像素點的值

g(x,y)=(1/16)* (f(x-1,y-1)+2f(x,y-1)+f(x+1,y-1)
+2f(x-1,y)+4f(x,y) + 2f(x+1,y)+
f(x-1,y+1)+2f(x,y+1)+f(x+1,y+1))------------------------------(1)

3>用模板掃描圖像中的每一個像素

在這裏插入圖片描述

圖1 模板掃描像素點示意圖

如圖1所示,使用高斯濾波模板從屏幕的左上角(從左到右),沒掃完一行換下一行(從上到下)掃完整個屏幕,最終完成一幀圖的高斯濾波。

3.FPGA實現

首先將RGB圖像轉換成Gray圖像
方法1:
在這裏插入圖片描述

圖2 R/G/B lane形成灰度圖像進行高斯濾波

如圖2所示,使用R/G/B單通道形成灰度圖像進入高斯濾波模塊。
方法二:

在這裏插入圖片描述

圖3 Y lane形成灰度圖像進行高斯濾波

如圖3所示,使用RGB圖像轉換成Ycbcr的圖像的Y通道形成灰度圖像進入高斯濾波模塊。

源碼:

`timescale 1ns/1ps

module gaussian_filter_3x3(
         input             clk,   //pixel clk
		 input             rst_n,
		 
		 input [15:0]       data_in, //16 bit RGB565 pixel 
		 input             data_in_en,
		 
		 output  reg [15:0]  data_out,
		 output            data_out_en
		 );
//------------------------------------
// 形成三行像素緩存
//-----------------------------------		 
wire [15:0] line0;
wire [15:0] line1;
wire [15:0] line2;
//-----------------------------------------
//形成3x3像素矩陣
//-----------------------------------------
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;
//---------------------------------------------
// shift_ram IP 形成三行像素緩存
//---------------------------------------------
line3x3 line3x3_inst(
        .clken(data_in_en),
	     .clock(clk),
	     .shiftin(data_in),
	     .shiftout(),
	     .taps0x(line0),
	     .taps1x(line1),
	     .taps2x(line2)
		  );
//----------------------------------------------------------------------
// Form an image matrix of three multiplied by three
//---------------------------------------------------------------------

always @(posedge clk or negedge rst_n) begin
  if(!rst_n) begin
     line0_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;
  end
  else if(data_in_en) begin  //像素有效信號
    line0_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;	 
  end
end

//---------------------------------------------------------------------------------------------------------------
// 計算最終結果
//---------------------------------------------------------------------------------------------------------------

always @(posedge clk or negedge rst_n) begin
  if(!rst_n)
    data_out <= 16'b0;
  else if(data_in_en)
    data_out <= (line0_data0 + line0_data1*2 + line0_data2 + line1_data0*2 + line1_data1*4 + line1_data2*2 + line2_data0 + line2_data1*2 + line2_data2)>>4;
	 //data_out <= line2_data1;
  else ;
end

endmodule 

仿真代碼:

`timescale 1ns/1ps
`define CLK_PERIOD 20
module gaussian_filter_3x3_tb();

reg clk;
reg rst_n;
reg [15:0] data_in;
reg data_in_en;

wire [15:0] data_out;
wire data_out_en;
		 
gaussian_filter_3x3  gaussian_filter_3x3_inst(
                 .clk(clk),
	             .rst_n(rst_n),
	
	             .data_in(data_in),
	             .data_in_en(data_in_en),
	
	             .data_out(data_out),
	             .data_out_en(data_out_en)
				 );	

initial begin
  clk = 0;
  rst_n = 0;
  data_in_en = 0;
  #(`CLK_PERIOD*10);
  rst_n = 1;
  #(`CLK_PERIOD*10);
  data_in_en = 1;
  #(`CLK_PERIOD*10000);
  $stop;
end	

always #(`CLK_PERIOD/2)	 clk = ~clk;

always @(posedge clk or negedge rst_n) begin
  if(!rst_n)
    data_in <= 16'd0;
  else if(data_in_en)
    if(data_in == 16'd479)
	  data_in <= 16'd0;
    else	  
      data_in <= data_in + 16'd1;
  else 
    ;     
end 		 
endmodule 

仿真結果:

在這裏插入圖片描述

圖5 形成3x3的圖像矩陣

由圖5藍色框數據可知,IP緩存了三行一模一樣的數據,形成了三行數據的緩存;
由紅色框可知,一個時鐘形成了(x,y)爲中心的3x3像素矩陣。
在這裏插入圖片描述

圖6 高斯濾波的計算結果

由圖6的藍色框我們可以知道九個像素點爲[11,10,9;11,10,9;11,10,9]有公式(1)計算可得10,與紅色框裏邊的結果一致。
實驗結果:
在這裏插入圖片描述

圖7 實驗使用原圖

在這裏插入圖片描述

圖8 灰度圖像

在這裏插入圖片描述

圖9 灰度圖像經過高斯濾波後的圖像

總結:

至此,基於FPGA的三大圖像濾波(均值濾波、中值濾波、高斯濾波)處理已經講解完畢,其中的圖像處理效果需要大家自己去實驗,去對比。手機拍攝出來的畢竟有差距。
FPGA在前端捕獲到數據後首先要對視頻圖像做一個預處理,然後根據噪聲的來源,針對椒鹽噪聲進行中值濾波,針對高斯噪聲進行高斯濾波處理,均值濾波在圖像處理中也很常見。
歡迎關注微信公衆號:FPGA開源工作室
獲取更多學習資料。
FPGA開源工作室

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章