FPGAスタディnotes_image処理3_FPGAメディアンフィルターアルゴリズムの実装

FPGAスタディノート

画像処理アルゴリズム

1. 中值滤波算法
   1.1 原理
   1.2 FPGA实现中值滤波算法

1.中央値フィルタリングアルゴリズム

1.1原理
各ピクセルのグレー値を、そのポイントの特定のエリアウィンドウ内のすべてのピクセルのグレー値の中央値に設定します。
特徴:効果的にノイズを抑制し、画像のエッジ情報を保護します。これは古典的なノイズ平滑化方法であり、RGB画像形式の処理に使用できます。
方法:
データをサイズで並べ替えてから、順序付けられた数値の順序に従って中央値を見つけます。並べ替えアルゴリズム:バブル並べ替え、2分割並べ替えなどのソフトウェアアルゴリズム。ハードウェアに適した並べ替えアルゴリズムは少なくなります。
3 * 3画像テンプレート

  • 3行のピクセルを別々に並べ替えます
  • 3行のピクセルで、最大3ピクセル、中間3ピクセル、最小3ピクセルをそれぞれ並べ替えます。
  • 中央値を取得するには、最大最小、中央中央、最小最大を並べ替えます

1.2メディアンフィルターアルゴリズムのFPGA実装

  • プロジェクトの目標
    メディアンフィルターアルゴリズムを使用してソルトアンドペッパーノイズ画像のノイズを除去し、FPGAを介してTFTディスプレイに表示します。
    ここに画像の説明を挿入

  • プロジェクトツール
    ①ハードウェア:Intel Cyclone IV EシリーズFPGA開発ボード、5インチ(800 * 480)TFT容量性タッチスクリーン、
    ②ソフトウェア:Quartusソフトウェア、Picture2Hexソフトウェア、MATLAB

  • プロジェクトコンポーネントモジュール
    ①PLL:プロジェクトに必要なクロック生成1. SDRAMコントローラのクロックと、前記SDRAMクロック信号; 3. TFTスクリーンコントローラクロック
    ②UARTシリアルポートプロトコル(UART_RX、UART_TX)
    ③FIFO読み取り
    ④書き込みFIFOを
    ⑤ SDRAMコントロールモジュール
    ⑥TFTスクリーンコントロールモジュール
    ∥メディアンフィルターモジュール

  • Verilogコード

/*
1. 分别对三行像素进行排序
2. 分别对三行像素中:3个最大值,3个中间值,3个最小值,进行排序
3. 对:3最大值中的最小值,3个中间值中的中间值,3个最小值中的最大值,进行排序,得到中值
*/

module median_filter_r0(
		input							clk, //33MHZ
		input							rst_n,
		input			[15:0]			data_in, //灰度像素输入
		input							data_in_en,//lcd显示有效区使能信号
		
		input							hs_in,//行同步信号输入
		input							vs_in,//场同步信号输入
		
		output	wire	[15:0]			data_out,//中值处理后灰度像素输出
		output	wire	 				data_out_en,
		
		output	wire					hs_out,//行同步信号输出
		output	wire					vs_out//场同步信号输出
);
//----timing declaration----
	reg			hs_reg0;
	reg			hs_reg1;
	reg			hs_reg2;
				
	reg			vs_reg0;
	reg			vs_reg1;
	reg			vs_reg2;
				
	reg			de_reg0;
	reg			de_reg1;
	reg			de_reg2;
	
	
//----pipeline declaration----	
	wire [15:0] row0;
	wire [15:0] row1;
	wire [15:0] row2;
	
	reg  [15:0]	r0_c0;
	reg  [15:0]	r0_c1;
	reg  [15:0]	r0_c2;
	
	reg  [15:0]	r1_c0;
	reg  [15:0]	r1_c1;
	reg  [15:0]	r1_c2;
	
	reg  [15:0]	r2_c0;
	reg  [15:0]	r2_c1;
	reg  [15:0]	r2_c2;
	
	
	reg  [15:0]	r0_max;
	reg  [15:0]	r0_mid;
	reg  [15:0]	r0_min;

	reg  [15:0]	r1_max;
	reg  [15:0]	r1_mid;
	reg  [15:0]	r1_min;

	reg  [15:0]	r2_max;
	reg  [15:0]	r2_mid;
	reg  [15:0]	r2_min;
	
	
	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;
	
	reg  [15:0] mid;
	
//--------------------------------------------------
//----3行像素缓存--------------------------//
	shifter3_3 shifter3_3(
		.clken(data_in_en),
		.clock(clk),
		.shiftin(data_in),
		.shiftout(),
		.taps0x(row0),
		.taps1x(row1),
		.taps2x(row2)
	);
	
//----timing control-----------------------//
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			hs_reg0 <= 1'd0;
			hs_reg1 <= 1'd0;
			hs_reg2 <= 1'd0;
	
			vs_reg0 <= 1'd0;
			vs_reg1 <= 1'd0;
			vs_reg2 <= 1'd0;
	
			de_reg0 <= 1'd0;
			de_reg1 <= 1'd0;
			de_reg2 <= 1'd0;
		end
		else if(data_in_en)begin
			hs_reg0 <= hs_in;
			hs_reg1 <= hs_reg0;
			hs_reg2 <= hs_reg1;
	
			vs_reg0 <= vs_in;
			vs_reg1 <= vs_reg0;
			vs_reg2 <= vs_reg1;
	
			de_reg0 <= data_in_en;
			de_reg1 <= de_reg0;
			de_reg2 <= de_reg1;
		end
	end
//-----------------------------------------//

//----pipeline-----------------------------//
//----3*3 matix from image
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			r0_c0 <= 16'd0;
			r0_c1 <= 16'd0;
			r0_c2 <= 16'd0;

			r1_c0 <= 16'd0;
			r1_c1 <= 16'd0;
			r1_c2 <= 16'd0;

			r2_c0 <= 16'd0;
			r2_c1 <= 16'd0;
			r2_c2 <= 16'd0;			
	end 
	else if(data_in_en)begin
			r0_c0 <= row0;
			r0_c1 <= r0_c0;
			r0_c2 <= r0_c1;

			r1_c0 <= row1;
			r1_c1 <= r1_c0;
			r1_c2 <= r1_c1;

			r2_c0 <= row2;
			r2_c1 <= r2_c0;
			r2_c2 <= r2_c1;
	end
end
//------------------------------------------------------------------
//----1.分别对三行像素进行排序r0_max, r10_max,r2_max
//----r0------------------------------------------
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			r0_max <= 16'd0;
			r0_mid <= 16'd0;
			r0_min <= 16'd0;		
		end 
		else if(data_in_en)begin
	
			if((r0_c0>=r0_c1)&&(r0_c0>=r0_c2))begin//r0_max <= r0_c0
				r0_max <= r0_c0;
				if(r0_c1>=r0_c2)begin
					r0_mid <= r0_c1;
					r0_min <= r0_c2;				
				end
				else begin
					r0_mid <= r0_c2;
					r0_min <= r0_c1;				
				end
			end
		
			else if((r0_c1>=r0_c0)&&(r0_c1>=r0_c2))begin//r0_max <= r0_c1;
				r0_max <= r0_c1;
				if(r0_c0>=r0_c2)begin
					r0_mid <= r0_c0;
					r0_min <= r0_c2;				
				end
				else begin
					r0_mid <= r0_c2;
					r0_min <= r0_c0;				
				end
			end
			
		else if((r0_c2>=r0_c0)&&(r0_c2>=r0_c1))begin//r0_max <= r0_c2;
				r0_max <= r0_c2;
				if(r0_c0>=r0_c1)begin
					r0_mid <= r0_c0;
					r0_min <= r0_c1;				
				end
				else begin
					r0_mid <= r0_c1;
					r0_min <= r0_c0;				
				end
		end
	end
	
end
//----r1--------------------------------------
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			r1_max <= 16'd0;
			r1_mid <= 16'd0;
			r1_min <= 16'd0;			
	end 
	else if(data_in_en)begin
	
		if((r1_c0>=r1_c1)&&(r1_c0>=r1_c2))begin//r0_max <= r0_c0
			r1_max <= r1_c0;
			if(r1_c1>=r1_c2)begin
				r1_mid <= r1_c1;
				r1_min <= r1_c2;				
			end
			else begin
				r1_mid <= r1_c2;
				r1_min <= r1_c1;				
			end
		end
		
		else if((r1_c1>=r1_c0)&&(r1_c1>=r1_c2))begin//r0_max <= r0_c1;
			r1_max <= r1_c1;
			if(r1_c0>=r1_c2)begin
				r1_mid <= r1_c0;
				r1_min <= r1_c2;				
			end
			else begin
				r1_mid <= r1_c2;
				r1_min <= r1_c0;				
			end
		end
		
	else if((r1_c2>=r1_c0)&&(r1_c2>=r1_c1))begin//r0_max <= r0_c2;
			r1_max <= r1_c2;
			if(r1_c0>=r1_c1)begin
				r1_mid <= r1_c0;
				r1_min <= r1_c1;				
			end
			else begin
				r1_mid <= r1_c1;
				r1_min <= r1_c0;				
			end
		end
	end
	
end
//----r2--------------------------------------
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			r2_max <= 16'd0;
			r2_mid <= 16'd0;
			r2_min <= 16'd0;			
	end 
	else if(data_in_en)begin
	
		if((r2_c0>=r2_c1)&&(r2_c0>=r2_c2))begin//r0_max <= r0_c0
			r2_max <= r2_c0;
			if(r2_c1>=r2_c2)begin
				r2_mid <= r2_c1;
				r2_min <= r2_c2;				
			end
			else begin
				r2_mid <= r2_c2;
				r2_min <= r2_c1;				
			end
		end
		
		else if((r2_c1>=r2_c0)&&(r2_c1>=r2_c2))begin//r0_max <= r0_c1;
			r2_max <= r2_c1;
			if(r2_c0>=r2_c2)begin
				r2_mid <= r2_c0;
				r2_min <= r2_c2;				
			end
			else begin
				r2_mid <= r2_c2;
				r2_min <= r2_c0;				
			end
		end
		
	else if((r2_c2>=r2_c0)&&(r2_c2>=r2_c1))begin//r0_max <= r0_c2;
			r2_max <= r2_c2;
			if(r2_c0>=r2_c1)begin
				r2_mid <= r2_c0;
				r2_min <= r2_c1;				
			end
			else begin
				r2_mid <= r2_c1;
				r2_min <= r2_c0;				
			end
		end
	end
	
end
//--------------------------------------------------------------------
//----2. 分别对三行像素中:3个最大值,3个中间值,3个最小值,进行排序
//----3个最大值------------------------------------------------
	always@(posedge clk or negedge rst_n)begin
	
		if(!rst_n)begin
			max_max <= 16'd0;
			max_mid <= 16'd0;
			max_min <= 16'd0;			
		end
		else if(data_in_en)begin
			if((r0_max >= r1_max)&&(r0_max >= r2_max))begin//max_max <= r0_max
				max_max <= r0_max;
				if((r1_max >= r2_max))begin
					max_mid <= r1_max;
					max_min <= r2_max;						
				end 
				else begin
					max_mid <= r2_max;
					max_min <= r1_max;				
				end		
		end
		else if((r1_max >= r0_max)&&(r1_max >= r2_max))begin//max_max <= r1_max;
				max_max <= r1_max;
				if((r0_max >= r2_max))begin
					max_mid <= r0_max;
					max_min <= r2_max;						
				end 
				else begin
					max_mid <= r2_max;
					max_min <= r0_max;				
				end		
		end
		else if((r2_max >= r0_max)&&(r2_max >= r1_max))begin//max_max <= r2_max;
				max_max <= r2_max;
				if((r0_max >= r1_max))begin
					max_mid <= r0_max;
					max_min <= r1_max;						
				end 
				else begin
					max_mid <= r1_max;
					max_min <= r0_max;				
				end		
			end
		end
		
	end
//----3个中间值------------------------------------------------
	always@(posedge clk or negedge rst_n)begin
	
		if(!rst_n)begin
			mid_max <= 16'd0;
			mid_mid <= 16'd0;
			mid_min <= 16'd0;			
		end
		else if(data_in_en)begin
			if((r0_mid >= r1_mid)&&(r0_mid >= r2_mid))begin//mid_max <= r0_mid
				mid_max <= r0_mid;
				if((r1_mid >= r2_mid))begin
					mid_mid <= r1_mid;
					mid_min <= r2_mid;						
				end 
				else begin
					mid_mid <= r2_mid;
					mid_min <= r1_mid;				
				end		
		end
		else if((r1_mid >= r0_mid)&&(r1_mid >= r2_mid))begin//mid_max <= r1_mid;
				mid_max <= r1_mid;
				if((r0_mid >= r2_mid))begin
					mid_mid <= r0_mid;
					mid_min <= r2_mid;						
				end 
				else begin
					mid_mid <= r2_mid;
					mid_min <= r0_mid;				
				end		
		end
		else if((r2_mid >= r0_mid)&&(r2_mid >= r1_mid))begin//mid_max <= r2_mid;
				mid_max <= r2_mid;
				if((r0_mid >= r1_mid))begin
					mid_mid <= r0_mid;
					mid_min <= r1_mid;						
				end 
				else begin
					mid_mid <= r1_mid;
					mid_min <= r0_mid;				
				end		
			end
		end
		
	end

//----3个最小值------------------------------------------------
	always@(posedge clk or negedge rst_n)begin
	
		if(!rst_n)begin
			min_max <= 16'd0;
			min_mid <= 16'd0;
			min_min <= 16'd0;			
		end
		else if(data_in_en)begin
			if((r0_min >= r1_min)&&(r0_min >= r2_min))begin//min_max <= r0_min
				min_max <= r0_min;
				if((r1_min >= r2_min))begin
					min_mid <= r1_min;
					min_min <= r2_min;						
				end 
				else begin
					min_mid <= r2_min;
					min_min <= r1_min;				
				end		
		end
		else if((r1_min >= r0_min)&&(r1_min >= r2_min))begin//min_max <= r1_min;
				min_max <= r1_min;
				if((r0_min >= r2_min))begin
					min_mid <= r0_min;
					min_min <= r2_min;						
				end 
				else begin
					min_mid <= r2_min;
					min_min <= r0_min;				
				end		
		end
		else if((r2_min >= r0_min)&&(r2_min >= r1_min))begin//min_max <= r2_min;
				min_max <= r2_min;
				if((r0_min >= r1_min))begin
					min_mid <= r0_min;
					min_min <= r1_min;						
				end 
				else begin
					min_mid <= r1_min;
					min_min <= r0_min;				
				end		
			end
		end
		
	end
//---------------------------------------------------------------------------------
//----3. 对:3个最大值中的最小值,3个中间值中的中间值,3个最小值中的最大值,进行排序,得到中值
	always@(posedge clk or negedge rst_n)begin
	
		if(!rst_n)
			mid <= 16'd0;			
		else if(data_in_en)begin
			if(((max_min >= mid_mid)&&(max_min < min_max))||((max_min < mid_mid)&&(max_min >= min_max)) )//mid <= max_min;
				mid <= max_min;
			else if(((mid_mid >= max_min)&&(mid_mid < min_max))||((mid_mid < max_min)&&(mid_mid >= min_max)) )//mid <= mid_mid;
				mid <= mid_mid;
			else if(((min_max >= max_min)&&(min_max < mid_mid))||((min_max < max_min)&&(min_max >= mid_mid)) )//mid <= min_max;
				mid <= min_max;
			else;
		end		
		else;

	end
//----result-------------------------------------------------------------------------
	assign data_out = mid;
	assign data_out_en = de_reg2;
	assign hs_out = hs_reg2;
	assign vs_out = vs_reg2;
//-----------------------------------------------------------------------------------
endmodule


  • プロジェクト結果
    5インチTFT静電容量式タッチスクリーン
    画像:800 * 480ピクセル
    (1)。(Yiyanqianxi ^^)元のネットワーク画像:
    ここに画像の説明を挿入
    (2)。FPGAディスプレイの元の画像:
    ここに画像の説明を挿入
    (3)ソルトアンドペッパーノイズ画像を追加:

  • ソルト&ペッパーノイズ密度= 0.1
    ここに画像の説明を挿入 (4)。FPGAメディアンフィルター処理図:

  • ソルト&ペッパーノイズ密度= 0.1
    ここに画像の説明を挿入
    プロジェクト結果分析:

  • 図3と図4を比較すると、メディアンフィルターアルゴリズムが塩とコショウのノイズを効果的に除去できることがわかります。


参考資料:「FPGAシステム設計・検証実践ガイド」
【注】:個人学習ノート、間違いがありましたら、お気軽に教えてください、丁寧です~~~


おすすめ

転載: blog.csdn.net/weixin_50722839/article/details/113763837