基于FPGA灰度图像高斯滤波算法的实现

基于FPGA灰度图像高斯滤波算法的实现

欢迎添加QQ:2639406604一起交流

1.内容概要

高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。
一位高斯分布:
基于FPGA灰度图像高斯滤波算法的实现_第1张图片
二位高斯分布:
基于FPGA灰度图像高斯滤波算法的实现_第2张图片
高斯滤波后图像被平滑的程度取决于标准差。它的输出是临域像素的加权平均,同时离中心越近的像素权重越高。因此,相对于均值滤波(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>用模板扫描图像中的每一个像素

基于FPGA灰度图像高斯滤波算法的实现_第3张图片

图1 模板扫描像素点示意图

如图1所示,使用高斯滤波模板从屏幕的左上角(从左到右),没扫完一行换下一行(从上到下)扫完整个屏幕,最终完成一帧图的高斯滤波。

3.FPGA实现

首先将RGB图像转换成Gray图像
方法1:
基于FPGA灰度图像高斯滤波算法的实现_第4张图片

图2 R/G/B lane形成灰度图像进行高斯滤波

如图2所示,使用R/G/B单通道形成灰度图像进入高斯滤波模块。
方法二:

基于FPGA灰度图像高斯滤波算法的实现_第5张图片

图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 

仿真结果:

基于FPGA灰度图像高斯滤波算法的实现_第6张图片

图5 形成3x3的图像矩阵

由图5蓝色框数据可知,IP缓存了三行一模一样的数据,形成了三行数据的缓存;
由红色框可知,一个时钟形成了(x,y)为中心的3x3像素矩阵。
基于FPGA灰度图像高斯滤波算法的实现_第7张图片

图6 高斯滤波的计算结果

由图6的蓝色框我们可以知道九个像素点为[11,10,9;11,10,9;11,10,9]有公式(1)计算可得10,与红色框里边的结果一致。
实验结果:
基于FPGA灰度图像高斯滤波算法的实现_第8张图片

图7 实验使用原图

图8 灰度图像

基于FPGA灰度图像高斯滤波算法的实现_第9张图片

图9 灰度图像经过高斯滤波后的图像

总结:

至此,基于FPGA的三大图像滤波(均值滤波、中值滤波、高斯滤波)处理已经讲解完毕,其中的图像处理效果需要大家自己去实验,去对比。手机拍摄出来的毕竟有差距。
FPGA在前端捕获到数据后首先要对视频图像做一个预处理,然后根据噪声的来源,针对椒盐噪声进行中值滤波,针对高斯噪声进行高斯滤波处理,均值滤波在图像处理中也很常见。
欢迎关注微信公众号:FPGA开源工作室
获取更多学习资料。
FPGA开源工作室

你可能感兴趣的:(FPGA图像处理,FPGA数字图像处理)