FPGAスタディノート
画像処理アルゴリズム
1. 中值滤波算法
1.1 原理
1.2 FPGA实现中值滤波算法
1.中央値フィルタリングアルゴリズム
1.1原理
各ピクセルのグレー値を、そのポイントの特定のエリアウィンドウ内のすべてのピクセルのグレー値の中央値に設定します。
特徴:効果的にノイズを抑制し、画像のエッジ情報を保護します。これは古典的なノイズ平滑化方法であり、RGB画像形式の処理に使用できます。
方法:
データをサイズで並べ替えてから、順序付けられた数値の順序に従って中央値を見つけます。並べ替えアルゴリズム:バブル並べ替え、2分割並べ替えなどのソフトウェアアルゴリズム。ハードウェアに適した並べ替えアルゴリズムは少なくなります。
- 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システム設計・検証実践ガイド」
【注】:個人学習ノート、間違いがありましたら、お気軽に教えてください、丁寧です~~~