zz圖像卷積與濾波的一些知識點

Xinwei: 寫的通俗易懂,終於讓我這個不搞CV、不搞圖像的外行理解卷積和濾波了。html

 

圖像卷積與濾波的一些知識點算法

zouxy09@qq.com函數

http://blog.csdn.net/zouxy09oop

 

      以前在學習CNN的時候,有對卷積進行一些學習和整理,後來就爛尾了,如今稍微整理下,先放上來,以提醒和交流。學習

1、線性濾波與卷積的基本概念優化

      線性濾波能夠說是圖像處理最基本的方法,它能夠容許咱們對圖像進行處理,產生不少不一樣的效果。作法很簡單。首先,咱們有一個二維的濾波器矩陣(有個高大上的名字叫卷積核)和一個要處理的二維圖像。而後,對於圖像的每個像素點,計算它的鄰域像素和濾波器矩陣的對應元素的乘積,而後加起來,做爲該像素位置的值。這樣就完成了濾波過程。ui

      對圖像和濾波矩陣進行逐個元素相乘再求和的操做就至關於將一個二維的函數移動到另外一個二維函數的全部位置,這個操做就叫卷積或者協相關。卷積和協相關的差異是,卷積須要先對濾波矩陣進行180的翻轉,但若是矩陣是對稱的,那麼二者就沒有什麼差異了。spa

      Correlation 和 Convolution能夠說是圖像處理最基本的操做,但卻很是有用。這兩個操做有兩個很是關鍵的特色:它們是線性的,並且具備平移不變性shift-invariant。平移不變性指咱們在圖像的每一個位置都執行相同的操做。線性指這個操做是線性的,也就是咱們用每一個像素的鄰域的線性組合來代替這個像素。這兩個屬性使得這個操做很是簡單,由於線性操做是最簡單的,而後在全部地方都作一樣的操做就更簡單了。.net

      實際上,在信號處理領域,卷積有普遍的意義,並且有其嚴格的數學定義,但在這裏不關注這個。orm

      2D卷積須要4個嵌套循環4-double loop,因此它並不快,除非咱們使用很小的卷積核。這裏通常使用3x3或者5x5。並且,對於濾波器,也有必定的規則要求:

      1)濾波器的大小應該是奇數,這樣它纔有一箇中心,例如3x3,5x5或者7x7。有中心了,也有了半徑的稱呼,例如5x5大小的核的半徑就是2。

      2)濾波器矩陣全部的元素之和應該要等於1,這是爲了保證濾波先後圖像的亮度保持不變。固然了,這不是硬性要求了。

      3)若是濾波器矩陣全部元素之和大於1,那麼濾波後的圖像就會比原圖像更亮,反之,若是小於1,那麼獲得的圖像就會變暗。若是和爲0,圖像不會變黑,但也會很是暗。

      4)對於濾波後的結構,可能會出現負數或者大於255的數值。對這種狀況,咱們將他們直接截斷到0和255之間便可。對於負數,也能夠取絕對值。

2、神奇的卷積核

      上面說到,對圖像的濾波處理就是對圖像應用一個小小的卷積核,那這個小小的卷積核到底有哪些魔法,能讓一個圖像從慘不忍睹變得秀色可餐。下面咱們一塊兒來領略下一些簡單但不簡單的卷積核的魔法。

2.一、啥也不作

      哈哈,你們能夠看到啥了嗎?這個濾波器啥也沒有作,獲得的圖像和原圖是同樣的。由於只有中心點的值是1。鄰域點的權值都是0,對濾波後的取值沒有任何影響。

      下面咱們動點真格的。

2.二、圖像銳化濾波器Sharpness Filter

      圖像的銳化和邊緣檢測很像,首先找到邊緣,而後把邊緣加到原來的圖像上面,這樣就強化了圖像的邊緣,使圖像看起來更加銳利了。這二者操做統一塊兒來就是銳化濾波器了,也就是在邊緣檢測濾波器的基礎上,再在中心的位置加1,這樣濾波後的圖像就會和原始的圖像具備一樣的亮度了,可是會更加銳利。

      咱們把核加大,就能夠獲得更加精細的銳化效果

      另外,下面的濾波器會更強調邊緣:

      主要是強調圖像的細節。最簡單的3x3的銳化濾波器以下:

      其實是計算當前點和周圍點的差異,而後將這個差異加到原來的位置上。另外,中間點的權值要比全部的權值和大於1,意味着這個像素要保持原來的值。

2.三、邊緣檢測Edge Detection

      咱們要找水平的邊緣:須要注意的是,這裏矩陣的元素和是0,因此濾波後的圖像會很暗,只有邊緣的地方是有亮度的。

      爲何這個濾波器能夠尋找到水平邊緣呢?由於用這個濾波器卷積至關於求導的離散版本:你將當前的像素值減去前一個像素值,這樣你就能夠獲得這個函數在這兩個位置的差異或者斜率。下面的濾波器能夠找到垂直方向的邊緣,這裏像素上和下的像素值都使用:

      再下面這個濾波器能夠找到45度的邊緣:取-2不爲了什麼,只是爲了讓矩陣的元素和爲0而已。

      那下面這個濾波器就能夠檢測全部方向的邊緣:

      爲了檢測邊緣,咱們須要在圖像對應的方向計算梯度。用下面的卷積核來卷積圖像,就能夠了。但在實際中,這種簡單的方法會把噪聲也放大了。另外,須要注意的是,矩陣全部的值加起來要是0.

2.四、浮雕Embossing Filter

      浮雕濾波器能夠給圖像一種3D陰影的效果。只要將中心一邊的像素減去另外一邊的像素就能夠了。這時候,像素值有多是負數,咱們將負數當成陰影,將正數當成光,而後咱們對結果圖像加上128的偏移。這時候,圖像大部分就變成灰色了。

      下面是45度的浮雕濾波器

      咱們只要加大濾波器,就能夠獲得更加誇張的效果了

      這種效果很是的漂亮,就像是將一副圖像雕刻在一塊石頭上面同樣,而後從一個方向照亮它。它和前面的濾波器不一樣,它是非對稱的。另外,它會產生負數值,因此咱們須要將結果偏移,以獲得圖像灰度的範圍。

      A:原圖像。B:銳化。C:邊緣檢測。D:浮雕

2.五、均值模糊Box Filter (Averaging)

      咱們能夠將當前像素和它的四鄰域的像素一塊兒取平均,而後再除以5,或者直接在濾波器的5個地方取0.2的值便可,以下圖:

      能夠看到,這個模糊仍是比較溫柔的,咱們能夠把濾波器變大,這樣就會變得粗暴了:注意要將和再除以13.

      因此,若是你想要更模糊的效果,加大濾波器的大小便可。或者對圖像應用屢次模糊也能夠。

 

2.六、高斯模糊

      均值模糊很簡單,但不是很平滑。高斯模糊就有這個優勢,因此被普遍用在圖像降噪上。特別是在邊緣檢測以前,都會用來移除細節。高斯濾波器是一個低通濾波器。

 

2.七、運動模糊Motion Blur

      運動模糊能夠經過只在一個方向模糊達到,例以下面9x9的運動模糊濾波器。注意,求和結果要除以9。

      這個效果就好像,攝像機是從左上角移動的右下角。

3、卷積的計算

      對圖像處理而言,存在兩大類的方法:空域處理和頻域處理!空域處理是指直接對原始的像素空間進行計算,頻率處理是指先對圖像變換到頻域,再作濾波等處理。

3.一、空域計算-直接2D卷積

3.1.一、2D卷積

      直接2D卷積就是一開始說的那樣,對於圖像的每個像素點,計算它的鄰域像素和濾波器矩陣的對應元素的乘積,而後加起來,做爲該像素位置的值。

      直接的實現也稱爲暴力實現brute force,由於它嚴格按照定義來實現,沒有任何優化。固然了,在並行實現裏面,它也是比較靈活的。另外,也存在一個優化版本,若是咱們的kernel是separable可分的,那麼就能夠獲得一個快5倍左右的卷積方法。

2.1.二、邊界處理

      那捲積核遇到圖像邊緣怎麼辦?例如圖像頂部的像素,它的上面已經沒有像素了,那麼它的值如何計算?目前有四種主流的處理方法,咱們用一維卷積和均值濾波來講明下。

      咱們在1D圖像中,用每一個像素和它的二鄰域的平均值來取代它的值。假設咱們有個1D的圖像I是這樣的:

      對非圖像邊界的像素的操做比較簡單。假設咱們對I的第四個像素3作局部平均。也就是咱們用2,3和7作平均,來取代這個位置的像素值。也就是,平均會產生一副新的圖像J,這個圖像在相同位置J (4) = (I(3)+I(4)+I(5))/3 = (2+3+7)/3 = 4。一樣,咱們能夠獲得J(3) = (I(2)+I(3)+I(4))/3 =(4+2+3)/3 = 3。須要注意的是,新圖像的每一個像素都取決於舊的圖像,在計算J (4)的時候用J (3)是不對的,而是用I(3),I(4)和I(5)。因此每一個像素都是它和它鄰域兩個像素的平均。平均是線性的操做,由於每一個新的像素都是舊像素的線性組合。

      對卷積,也有必需要考慮的狀況是,在圖像邊界的時候,怎麼辦?J(1)的值應該是什麼?它取決於I(0),I(1)和I(2)。可是咱們沒有I(0)呀!圖像左邊沒有值了。有四種方式來處理這個問題:

      1)第一種就是想象I是無限長的圖像的一部分,除了咱們給定值的部分,其餘部分的像素值都是0。在這種狀況下,I(0)=0。因此J(1) = (I(0) + I(1) + I(2))/3 = (0 + 5 + 4)/3= 3. 一樣,J(10) = (I(9)+I(10)+I(11))/3 = (3+ 6 + 0)/3 = 3.

      2)第二種方法也是想象I是無限圖像的一部分。但沒有指定的部分是用圖像邊界的值進行拓展。在咱們的例子中,由於圖像I最左邊的值I(1)=5,因此它左邊的全部值,咱們都認爲是5 。而圖像右邊的全部的值,咱們都認爲和右邊界的值I(10)同樣,都是6。這時候J(1) = (I(0) + I(1) + I(2))/3 = (5 + 5 + 4)/3= 14/3. 而J(10) = (I(9)+I(10)+I(11))/3 = (3 + 6 + 6)/3 = 5。

      3)第三種狀況就是認爲圖像是週期性的。也就是I不斷的重複。週期就是I的長度。在咱們這裏,I(0)和I(10)的值就是同樣的,I(11)的值和I(1)的值也是同樣的。因此J(1) = (I(0) + I(1) + I(2))/3= (I(10) + I(1)+ I(2))/3 = (6 + 5 + 4)/3 = 5 。

      4)最後一種狀況就是無論其餘地方了。咱們以爲I以外的狀況是沒有定義的,因此沒辦法使用這些沒有定義的值,因此要使用圖像I沒有定義的值的像素都沒辦法計算。在這裏,J(1)和J(10)都沒辦法計算,因此輸出J會比原圖像I要小。

      這四種方法有各自的優缺點。若是咱們想象咱們使用的圖像只是世界的一個小窗口,而後咱們須要使用窗口邊界外的值,那麼通常來講,外面的值和邊界上的值是幾乎類似的,因此第二種方法可能更說得過去。

2.二、頻域計算-快速傅里葉變換FFT卷積

      這個快速實現得益於卷積定理:時域上的卷積等於頻域上的乘積。因此將咱們的圖像和濾波器經過算法變換到頻域後,直接將他們相乘,而後再變換回時域(也就是圖像的空域)就能夠了。

      o表示矩陣逐元素相乘。那用什麼方法將空域的圖像和濾波器變換到頻域了。那就是鼎鼎大名的Fast Fourier Transformation 快速傅里葉變換FFT(其實,在CUDA裏面,已經實現了FFT了)。

      要在頻域中對一副圖像進行濾波,濾波器的大小和圖像的大小必需要匹配,這樣二者的相乘才容易。由於通常濾波器的大小比圖像要小,因此咱們須要拓展咱們的kernel,讓它和圖像的大小一致。

      由於CUDA中的FFT實現是週期的,因此kernel的值也要安排成這樣,以支持這種週期性。

      爲了保證圖像邊界的像素也能夠獲得響應輸出,咱們也須要拓展咱們的輸入圖像。同時,拓展的方式也要支持週期表達。

      若是隻是使用卷積定理,沒有對輸入進行任何修改的話,那麼咱們獲得的是週期卷積的結果。但這可能不是咱們要的,由於週期卷積會對輸入數據進行週期填補,引入一些artifacts。

      給定N長度的I和K,爲了獲得線性卷積,咱們須要對I和K進行zero padding。爲何要補0,由於DFT假定了輸入是無限和週期的,週期是N。 

      如上圖,對於I和K,若是沒有padding的話,隱含着會假定I和K是週期的,以他們的長度N爲週期。圖中原本N長度的I和K都是黑色虛線的部分,而後若是沒有padding,隱含着就會在N以外,加上一樣的無數個I,如紅色虛線部分,加上了一個週期。對K也是這樣。若是是zero padding的話,在黑色虛線的其餘地方都全是0了,如圖中藍色部分。將I和K卷積,若是沒有padding,如黑色虛線,會有紅色那部分的artifact。若是有padding,就是藍色實線。

 4、實驗代碼

      這是第二部分的Matlab實驗代碼:

 


5、參考文獻

 

[1] Correlation and Convolution.pdf

[2] Lode's Computer GraphicsTutorial Image Filtering

圖像卷積與濾波的一些知識點

zouxy09@qq.com

http://blog.csdn.net/zouxy09

 

      以前在學習CNN的時候,有對卷積進行一些學習和整理,後來就爛尾了,如今稍微整理下,先放上來,以提醒和交流。

1、線性濾波與卷積的基本概念

      線性濾波能夠說是圖像處理最基本的方法,它能夠容許咱們對圖像進行處理,產生不少不一樣的效果。作法很簡單。首先,咱們有一個二維的濾波器矩陣(有個高大上的名字叫卷積核)和一個要處理的二維圖像。而後,對於圖像的每個像素點,計算它的鄰域像素和濾波器矩陣的對應元素的乘積,而後加起來,做爲該像素位置的值。這樣就完成了濾波過程。

      對圖像和濾波矩陣進行逐個元素相乘再求和的操做就至關於將一個二維的函數移動到另外一個二維函數的全部位置,這個操做就叫卷積或者協相關。卷積和協相關的差異是,卷積須要先對濾波矩陣進行180的翻轉,但若是矩陣是對稱的,那麼二者就沒有什麼差異了。

      Correlation 和 Convolution能夠說是圖像處理最基本的操做,但卻很是有用。這兩個操做有兩個很是關鍵的特色:它們是線性的,並且具備平移不變性shift-invariant。平移不變性指咱們在圖像的每一個位置都執行相同的操做。線性指這個操做是線性的,也就是咱們用每一個像素的鄰域的線性組合來代替這個像素。這兩個屬性使得這個操做很是簡單,由於線性操做是最簡單的,而後在全部地方都作一樣的操做就更簡單了。

      實際上,在信號處理領域,卷積有普遍的意義,並且有其嚴格的數學定義,但在這裏不關注這個。

      2D卷積須要4個嵌套循環4-double loop,因此它並不快,除非咱們使用很小的卷積核。這裏通常使用3x3或者5x5。並且,對於濾波器,也有必定的規則要求:

      1)濾波器的大小應該是奇數,這樣它纔有一箇中心,例如3x3,5x5或者7x7。有中心了,也有了半徑的稱呼,例如5x5大小的核的半徑就是2。

      2)濾波器矩陣全部的元素之和應該要等於1,這是爲了保證濾波先後圖像的亮度保持不變。固然了,這不是硬性要求了。

      3)若是濾波器矩陣全部元素之和大於1,那麼濾波後的圖像就會比原圖像更亮,反之,若是小於1,那麼獲得的圖像就會變暗。若是和爲0,圖像不會變黑,但也會很是暗。

      4)對於濾波後的結構,可能會出現負數或者大於255的數值。對這種狀況,咱們將他們直接截斷到0和255之間便可。對於負數,也能夠取絕對值。

2、神奇的卷積核

      上面說到,對圖像的濾波處理就是對圖像應用一個小小的卷積核,那這個小小的卷積核到底有哪些魔法,能讓一個圖像從慘不忍睹變得秀色可餐。下面咱們一塊兒來領略下一些簡單但不簡單的卷積核的魔法。

2.一、啥也不作

      哈哈,你們能夠看到啥了嗎?這個濾波器啥也沒有作,獲得的圖像和原圖是同樣的。由於只有中心點的值是1。鄰域點的權值都是0,對濾波後的取值沒有任何影響。

      下面咱們動點真格的。

2.二、圖像銳化濾波器Sharpness Filter

      圖像的銳化和邊緣檢測很像,首先找到邊緣,而後把邊緣加到原來的圖像上面,這樣就強化了圖像的邊緣,使圖像看起來更加銳利了。這二者操做統一塊兒來就是銳化濾波器了,也就是在邊緣檢測濾波器的基礎上,再在中心的位置加1,這樣濾波後的圖像就會和原始的圖像具備一樣的亮度了,可是會更加銳利。

      咱們把核加大,就能夠獲得更加精細的銳化效果

      另外,下面的濾波器會更強調邊緣:

      主要是強調圖像的細節。最簡單的3x3的銳化濾波器以下:

      其實是計算當前點和周圍點的差異,而後將這個差異加到原來的位置上。另外,中間點的權值要比全部的權值和大於1,意味着這個像素要保持原來的值。

2.三、邊緣檢測Edge Detection

      咱們要找水平的邊緣:須要注意的是,這裏矩陣的元素和是0,因此濾波後的圖像會很暗,只有邊緣的地方是有亮度的。

      爲何這個濾波器能夠尋找到水平邊緣呢?由於用這個濾波器卷積至關於求導的離散版本:你將當前的像素值減去前一個像素值,這樣你就能夠獲得這個函數在這兩個位置的差異或者斜率。下面的濾波器能夠找到垂直方向的邊緣,這裏像素上和下的像素值都使用:

      再下面這個濾波器能夠找到45度的邊緣:取-2不爲了什麼,只是爲了讓矩陣的元素和爲0而已。

      那下面這個濾波器就能夠檢測全部方向的邊緣:

      爲了檢測邊緣,咱們須要在圖像對應的方向計算梯度。用下面的卷積核來卷積圖像,就能夠了。但在實際中,這種簡單的方法會把噪聲也放大了。另外,須要注意的是,矩陣全部的值加起來要是0.

2.四、浮雕Embossing Filter

      浮雕濾波器能夠給圖像一種3D陰影的效果。只要將中心一邊的像素減去另外一邊的像素就能夠了。這時候,像素值有多是負數,咱們將負數當成陰影,將正數當成光,而後咱們對結果圖像加上128的偏移。這時候,圖像大部分就變成灰色了。

      下面是45度的浮雕濾波器

      咱們只要加大濾波器,就能夠獲得更加誇張的效果了

      這種效果很是的漂亮,就像是將一副圖像雕刻在一塊石頭上面同樣,而後從一個方向照亮它。它和前面的濾波器不一樣,它是非對稱的。另外,它會產生負數值,因此咱們須要將結果偏移,以獲得圖像灰度的範圍。

      A:原圖像。B:銳化。C:邊緣檢測。D:浮雕

2.五、均值模糊Box Filter (Averaging)

      咱們能夠將當前像素和它的四鄰域的像素一塊兒取平均,而後再除以5,或者直接在濾波器的5個地方取0.2的值便可,以下圖:

      能夠看到,這個模糊仍是比較溫柔的,咱們能夠把濾波器變大,這樣就會變得粗暴了:注意要將和再除以13.

      因此,若是你想要更模糊的效果,加大濾波器的大小便可。或者對圖像應用屢次模糊也能夠。

 

2.六、高斯模糊

      均值模糊很簡單,但不是很平滑。高斯模糊就有這個優勢,因此被普遍用在圖像降噪上。特別是在邊緣檢測以前,都會用來移除細節。高斯濾波器是一個低通濾波器。

 

2.七、運動模糊Motion Blur

      運動模糊能夠經過只在一個方向模糊達到,例以下面9x9的運動模糊濾波器。注意,求和結果要除以9。

      這個效果就好像,攝像機是從左上角移動的右下角。

3、卷積的計算

      對圖像處理而言,存在兩大類的方法:空域處理和頻域處理!空域處理是指直接對原始的像素空間進行計算,頻率處理是指先對圖像變換到頻域,再作濾波等處理。

3.一、空域計算-直接2D卷積

3.1.一、2D卷積

      直接2D卷積就是一開始說的那樣,對於圖像的每個像素點,計算它的鄰域像素和濾波器矩陣的對應元素的乘積,而後加起來,做爲該像素位置的值。

      直接的實現也稱爲暴力實現brute force,由於它嚴格按照定義來實現,沒有任何優化。固然了,在並行實現裏面,它也是比較靈活的。另外,也存在一個優化版本,若是咱們的kernel是separable可分的,那麼就能夠獲得一個快5倍左右的卷積方法。

2.1.二、邊界處理

      那捲積核遇到圖像邊緣怎麼辦?例如圖像頂部的像素,它的上面已經沒有像素了,那麼它的值如何計算?目前有四種主流的處理方法,咱們用一維卷積和均值濾波來講明下。

      咱們在1D圖像中,用每一個像素和它的二鄰域的平均值來取代它的值。假設咱們有個1D的圖像I是這樣的:

      對非圖像邊界的像素的操做比較簡單。假設咱們對I的第四個像素3作局部平均。也就是咱們用2,3和7作平均,來取代這個位置的像素值。也就是,平均會產生一副新的圖像J,這個圖像在相同位置J (4) = (I(3)+I(4)+I(5))/3 = (2+3+7)/3 = 4。一樣,咱們能夠獲得J(3) = (I(2)+I(3)+I(4))/3 =(4+2+3)/3 = 3。須要注意的是,新圖像的每一個像素都取決於舊的圖像,在計算J (4)的時候用J (3)是不對的,而是用I(3),I(4)和I(5)。因此每一個像素都是它和它鄰域兩個像素的平均。平均是線性的操做,由於每一個新的像素都是舊像素的線性組合。

      對卷積,也有必需要考慮的狀況是,在圖像邊界的時候,怎麼辦?J(1)的值應該是什麼?它取決於I(0),I(1)和I(2)。可是咱們沒有I(0)呀!圖像左邊沒有值了。有四種方式來處理這個問題:

      1)第一種就是想象I是無限長的圖像的一部分,除了咱們給定值的部分,其餘部分的像素值都是0。在這種狀況下,I(0)=0。因此J(1) = (I(0) + I(1) + I(2))/3 = (0 + 5 + 4)/3= 3. 一樣,J(10) = (I(9)+I(10)+I(11))/3 = (3+ 6 + 0)/3 = 3.

      2)第二種方法也是想象I是無限圖像的一部分。但沒有指定的部分是用圖像邊界的值進行拓展。在咱們的例子中,由於圖像I最左邊的值I(1)=5,因此它左邊的全部值,咱們都認爲是5 。而圖像右邊的全部的值,咱們都認爲和右邊界的值I(10)同樣,都是6。這時候J(1) = (I(0) + I(1) + I(2))/3 = (5 + 5 + 4)/3= 14/3. 而J(10) = (I(9)+I(10)+I(11))/3 = (3 + 6 + 6)/3 = 5。

      3)第三種狀況就是認爲圖像是週期性的。也就是I不斷的重複。週期就是I的長度。在咱們這裏,I(0)和I(10)的值就是同樣的,I(11)的值和I(1)的值也是同樣的。因此J(1) = (I(0) + I(1) + I(2))/3= (I(10) + I(1)+ I(2))/3 = (6 + 5 + 4)/3 = 5 。

      4)最後一種狀況就是無論其餘地方了。咱們以爲I以外的狀況是沒有定義的,因此沒辦法使用這些沒有定義的值,因此要使用圖像I沒有定義的值的像素都沒辦法計算。在這裏,J(1)和J(10)都沒辦法計算,因此輸出J會比原圖像I要小。

      這四種方法有各自的優缺點。若是咱們想象咱們使用的圖像只是世界的一個小窗口,而後咱們須要使用窗口邊界外的值,那麼通常來講,外面的值和邊界上的值是幾乎類似的,因此第二種方法可能更說得過去。

2.二、頻域計算-快速傅里葉變換FFT卷積

      這個快速實現得益於卷積定理:時域上的卷積等於頻域上的乘積。因此將咱們的圖像和濾波器經過算法變換到頻域後,直接將他們相乘,而後再變換回時域(也就是圖像的空域)就能夠了。

      o表示矩陣逐元素相乘。那用什麼方法將空域的圖像和濾波器變換到頻域了。那就是鼎鼎大名的Fast Fourier Transformation 快速傅里葉變換FFT(其實,在CUDA裏面,已經實現了FFT了)。

      要在頻域中對一副圖像進行濾波,濾波器的大小和圖像的大小必需要匹配,這樣二者的相乘才容易。由於通常濾波器的大小比圖像要小,因此咱們須要拓展咱們的kernel,讓它和圖像的大小一致。

      由於CUDA中的FFT實現是週期的,因此kernel的值也要安排成這樣,以支持這種週期性。

      爲了保證圖像邊界的像素也能夠獲得響應輸出,咱們也須要拓展咱們的輸入圖像。同時,拓展的方式也要支持週期表達。

      若是隻是使用卷積定理,沒有對輸入進行任何修改的話,那麼咱們獲得的是週期卷積的結果。但這可能不是咱們要的,由於週期卷積會對輸入數據進行週期填補,引入一些artifacts。

      給定N長度的I和K,爲了獲得線性卷積,咱們須要對I和K進行zero padding。爲何要補0,由於DFT假定了輸入是無限和週期的,週期是N。 

      如上圖,對於I和K,若是沒有padding的話,隱含着會假定I和K是週期的,以他們的長度N爲週期。圖中原本N長度的I和K都是黑色虛線的部分,而後若是沒有padding,隱含着就會在N以外,加上一樣的無數個I,如紅色虛線部分,加上了一個週期。對K也是這樣。若是是zero padding的話,在黑色虛線的其餘地方都全是0了,如圖中藍色部分。將I和K卷積,若是沒有padding,如黑色虛線,會有紅色那部分的artifact。若是有padding,就是藍色實線。

 4、實驗代碼

      這是第二部分的Matlab實驗代碼:

 

clear,close all, clc
 
%% readimage
image =imread('test.jpg');
 
%% definefilter
% -----Identity filter -----
kernel =[0, 0, 0
                     0, 1, 0
                     0, 0, 0];
 
% -----Average Blur -----
kernel =[0, 1, 0
                     1, 1, 1
                     0, 1, 0] / 5;
 
% -----Gaussian Blur -----
kernel =fspecial('gaussian', 5 , 0.8);
 
% -----Motion Blur -----
kernel =[1, 0, 0, 0, 0
                     0, 1, 0, 0, 0
                     0, 0, 1, 0, 0
                     0, 0, 0, 1, 0
                     0, 0, 0, 0, 1] / 5;
                    
% -----Edges Detection -----
kernel =[-1, -1, -1
                     -1, 8, -1
                     -1, -1, -1];
 
% -----Sharpen filter -----
kernel =[-1, -1, -1
                     -1, 9, -1
                     -1, -1, -1];
                    
% -----Emboss filter -----
kernel =[-1, -1, 0
                     -1,  0,1
                     0,   1,1];
                    
%% convolethe image with defined kernel or filter
result =zeros(size(image));
result(:,:, 1) = conv2(double(image(:, :, 1)), double(kernel), 'same');
result(:,:, 2) = conv2(double(image(:, :, 2)), double(kernel), 'same');
result(:,:, 3) = conv2(double(image(:, :, 3)), double(kernel), 'same');
 
%% showthe result
imshow(image);
figure
imshow(uint8(result))

 

  

 

 5、參考文獻

 

[1] Correlation and Convolution.pdf

[2] Lode's Computer GraphicsTutorial Image Filtering

相關文章
相關標籤/搜索