基於FPGA的中值濾波器設計

簡介

學習本教程需要一定的基礎,主要參考<<基於FPGA的數字圖像處理原理及應用>>的第八章,建議大家可以先看看書上的內容,尤其是一些理論推導,這裏我就不詳細展開了。爲了簡化開發難度,這裏規定圖像格式爲6404808bit @60的灰度圖,也就是圖像分辨率爲640*480,一個像素佔8個bit,幀率爲60。

統計排序濾波

設r爲處理窗口半徑,I(x,y)爲輸入像素值,g(x,y)爲輸出像素值,則有如下定義:
g(x,y)=Sort(I(x+i,y+i),n) ,-r≤i≤r,-r≤j≤r,0≤n<(2r+1)^2.
令n=(2r+1)2/2,則上式變爲中值濾波器。常用的排序算子有冒泡排序、希爾排序即簡單排序等,以冒泡排序爲例,C++語言處理算法如下:
在這裏插入圖片描述
中值濾波能夠很好的消除椒鹽噪聲。效果圖如下所示:
在這裏插入圖片描述

基於FPGA的統計排序濾波器

並行全比較排序法

爲了區別相同的數值,對各個數值的輸入次序做如下規定:

  • 當前數值大於本數據之前輸入數據時,結果記爲1,小於或等於時記爲0.
  • 當前數值大於或等於本數據之後輸入數據時,結果記爲1,小於時記爲0.
  • 與自身比較記爲0.

利用此規則對輸入數據進行排序,如下表所示:
在這裏插入圖片描述
以3個數據d1,d2,d3的排序爲例,需要設計的比較器數目爲n(n-1)個。如下所示:

d_1≥d_2
d_1≥d_3
d_2>d_1
d_2≥d_3
d_3>d_1
d_3>d_2

整體設計與模塊劃分

採用與均值濾波類似的方法,先進行一維圖像行方向上的排序,再對列方向上的行排序結果進行排序,即可得到一個窗口方向上的排序。同樣的,行方向的對齊採用行緩存來實現,如下圖所示:
在這裏插入圖片描述
注意:並行全比較排序與C語言實現的冒泡排序結果,在某些特殊情況下還是有點差別的。如下所示:
在這裏插入圖片描述
(1) 如果使用C語言冒泡排序,目標值會被判定爲1,因爲這9個數的排序如下:
1, 1, 1, 1 ,1, 0, 0, 0, 0
其中值爲1,故判定爲1.
(2) 使用先行後列的全排序法,每行的中值如下:

1
0
0

再對這3個數進行排序,得到最終的中值爲0.與C語言冒泡排序判定結果不同。只有在1與0的比值爲5:4或4:5的情況下才會出現,其他比值則不會出現判定結果不同。即便某些情況下判定結果可能不同,但他們都是中值附近的值,都具有中值濾波的效果。自己可以多列幾種情況試試看。

想強調的是,先行後列的並行全比較排序和C語言的冒泡排序數據結果對比時,可能會出現某些數據不同,免得大家懷疑是程序編寫錯誤。

median_1d 模塊設計

全並行排序的計算步驟如下;
(1) 首先得到待排序的n個數據:可以通過打n-1拍得到。
(2) 進行全比較:當前數據與其他所有數據依次比較,並記錄比較結果。
(3) 將(2)中的記錄結果相加.
(4) 查找(3)中相加結果按指定次序輸出。
一維排序濾波電路設計如下所示:
在這裏插入圖片描述
在這裏插入圖片描述
需要注意的是:din_r[2]爲輸入第0個數據,din_r[1]爲輸入第1個數據,din_r[0]爲輸入第2個數據。
由於在求cmp_sum時,消耗了一個時鐘週期,所以在求dout時,需要先對輸入數據打一拍,即此時din_r[3]爲輸入第0個數據,din_r[2]爲輸入第1個數據,din_r[1]爲輸入第2個數據。

  • 當cmp_sum[0]==OUT_ID時,將第0個數據(din_r[3])賦值給dout,
  • 當cmp_sum[1]==OUT_ID時,將第1個數據(din_r[2])賦值給dout,
  • 當cmp_sum[2]==OUT_ID時,將第2個數據(din_r[1])賦值給dout。

從上圖可以看出,產生dout共需消耗5個時鐘週期,dout_vld需要和dout信號同步,故同樣需要對dout_vld打5拍,如下所示:
在這裏插入圖片描述
上圖中的KSZ爲窗口長度,KSZ的值爲3,故一行數據有兩個數據無法做中值處理,所以dout_vld信號產生代碼如下:
在這裏插入圖片描述

median_2d模塊設計

採用和均值濾波同樣的思路來處理,整個計算步驟如下:
(1) 計算一維行方向的排序結果輸出。
(2) 將第(1)步的結果接入第一個行緩存,第一個行緩存的輸出接入第二個行緩存,得到3行的一維輸出。
(3) 對第(2)步輸出的三個數據進行排序,得到結果輸出。
(4) 完成時序對齊。
二維運算的電路設計如下圖所示:
在這裏插入圖片描述
在這裏插入圖片描述
由於行FIFO讀出數據有一拍延時,所以median_1d輸出的數據需要延時一拍,以便於FIFO讀出數據對齊。從圖4-6可以看出,產生median_data共需消耗3個時鐘週期,median_vld有line_rd_en[2]產生,也需要延時3個時鐘週期,以便於median_data信號對齊,產生代碼如下:
在這裏插入圖片描述
由於median_vld由line_rd_en[1]產生,故已經捨去了兩行,所以此時不需要再與上其他信號了,注意與median_1d模塊的dout_vld做對比,自己理解一下。

仿真與調試

median_1d的測試激勵如下:
在這裏插入圖片描述
測試激勵主要是產生0-9共10個數據,仿真結果如下所示:
在這裏插入圖片描述
可以看出,中值結果是正確,尤其需要注意的是紅色框框裏的數據,8和1共產生了2次,這個地方使用書上的代碼是有問題的。具體的自己看代碼就知道了。

median_2d仿真有點麻煩,自己可以使用mspaint畫圖軟件產生10*10的黑白圖,然後再用qt將其轉成txt,最後再使用modelsim進行仿真。也可以自己寫測試激勵。最終中值濾波結果如下圖所示:
在這裏插入圖片描述

福利

本教程的所有verilog源碼以及上位機源碼都會公佈,微信掃描下面的二維碼關注[春哥筆記]公衆號,回覆“非線性濾波”即可Get源碼的獲取方式。
在這裏插入圖片描述

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