到底什麼是卷積?

轉載: https://blog.csdn.net/hxg2006/article/details/79626288 http://blog.csdn.net/chaipp0607/article/details/72236892

        https://www.zhihu.com/question/22298352

     在圖像處理領域,我們經常能聽到濾波,卷積之類的詞,其實他們都可以看做一種圖像的卷積操作,相對應的卷積核,卷積模板,濾波器,濾波模板,掃描窗其實也都是同一個東西。下面我們進一步討論圖像中的卷積操作核卷積的意義。

1、數字信號處理中卷積理解

    卷積一詞最開始出現在信號與線性系統中,信號與線性系統中討論的就是信號經過一個線性系統以後發生的變化。由於現實情況中常常是一個信號前一時刻的輸出影響着這一時刻的輸出,所在一般利用系統的單位響應與系統的輸入求卷積,以求得系統的輸出信號(當然要求這個系統是線性時不變的)。 
卷積的定義: 卷積是兩個變量在某範圍內相乘後求和的結果。如果卷積的變量是序列x(n)和h(n),則卷積的結果: 

                     這裏寫圖片描述

作者:果程C
鏈接:https://www.zhihu.com/question/22298352/answer/50940942
來源:知乎

對於初學者,我推薦用複利的例子來理解卷積可能更好理解一些:

小明存入100元錢,年利率是5%,按複利計算(即將每一年所獲利息加入本金,以計算下一年的利息),那麼在五年之後他能拿到的錢數是100(1+5\%)^5,如下表所示:


將這筆錢存入銀行的一年之後,小明又往銀行中存入了100元錢,年利率仍爲5%,那麼這筆錢按複利計算,到了第五年,將收回的錢數是100(1+5\%)^4,我們將這一結果作爲新的一行加入上面的表格中:

以此類推,如果小明每年都往銀行中存入新的100元錢,那麼這個收益表格將是這樣的:
<img src="https://pic1.zhimg.com/50/cfe98b9d33640fae02a21bf369f0459d_hd.jpg" data-rawwidth="1296" data-rawheight="284" class="origin_image zh-lightbox-thumb" width="1296" data-original="https://pic1.zhimg.com/cfe98b9d33640fae02a21bf369f0459d_r.jpg">可見,最終小明拿到的錢將等於他各年存入的錢分別計算複利之後得到的錢數的總和,即:

用求和符號來簡化這個公式,可以得到:
\sum_{i=0}^{5}{f(i)g(5-i)}, \mathrm{where} \ f(i)=100, g(5-i) = (1.05)^{5-i}
在上式中,f(i)爲小明的存錢函數,而g(i)爲存入銀行的每一筆錢的複利計算函數在這裏,小明最終得到的錢就是他的存錢函數和複利計算函數的卷積。
爲了更清晰地看到這一點,我們將這個公式推廣到連續的情況,也就是說,小明在從0t的這一段時間內,每時每刻都往銀行裏存錢,他的存錢函數爲f(\tau)\ (0\leq \tau\leq t),而銀行也對他存入的每一筆錢按複利公式計算收益:g(t-\tau)=(1+5\%)^{t-\tau},則小明到時間t將得到的總錢數爲:
\int_{0}^{t} f(\tau)g(t-\tau)d\tau=\int_{0}^{t} f(\tau)(1+5\%)^{t-\tau}d\tau
這也就是卷積的表達式了,上式可以記爲(f\ast g)(t)

相信通過上面這個例子,大家應該能夠很清晰地記住卷積公式了。下面我們再展開說兩句:
如果我們將小明的存款函數視爲一個信號發生(也就是激勵)的過程,而將複利函數g(t-\tau)視爲一個系統對信號的響應函數(也就是響應),那麼二者的卷積(f\ast g)(t)就可以看做是在t時刻對系統進行觀察,得到的觀察結果(也就是輸出)將是過去產生的所有信號經過系統的「處理/響應」後得到的結果的疊加,這也就是卷積的物理意義了。


作者:魚膩
鏈接:https://www.zhihu.com/question/22298352/answer/91131073
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

看了好多關於卷積的答案,看到這個例子才徹底地理解了這個過程~
關於卷積的一個血腥的講解
比如說你的老闆命令你幹活,你卻到樓下打檯球去了,後來被老闆發現,他非常氣憤,扇了你一巴掌(注意,這就是輸入信號,脈衝),於是你的臉上會漸漸地(賤賤地)鼓起來一個包,你的臉就是一個系統,而鼓起來的包就是你的臉對巴掌的響應,好,這樣就和信號系統建立起來意義對應的聯繫。下面還需要一些假設來保證論證的嚴謹:假定你的臉是線性時不變系統,也就是說,無論什麼時候老闆打你一巴掌,打在你臉的同一位置(這似乎要求你的臉足夠光滑,如果你說你長了很多青春痘,甚至整個臉皮處處連續處處不可導,那難度太大了,我就無話可說了哈哈),你的臉上總是會在相同的時間間隔內鼓起來一個相同高度的包來,並且假定以鼓起來的包的大小作爲系統輸出。好了,那麼,下面可以進入核心內容——卷積了!

如果你每天都到地下去打檯球,那麼老闆每天都要扇你一巴掌,不過當老闆打你一巴掌後,你5分鐘就消腫了,所以時間長了,你甚至就適應這種生活了……如果有一天,老闆忍無可忍,以0.5秒的間隔開始不間斷的扇你的過程,這樣問題就來了,第一次扇你鼓起來的包還沒消腫,第二個巴掌就來了,你臉上的包就可能鼓起來兩倍高,老闆不斷扇你,脈衝不斷作用在你臉上,效果不斷疊加了,這樣這些效果就可以求和了,結果就是你臉上的包的高度隨時間變化的一個函數了(注意理解);如果老闆再狠一點,頻率越來越高,以至於你都辨別不清時間間隔了,那麼,求和就變成積分了。可以這樣理解,在這個過程中的某一固定的時刻,你的臉上的包的鼓起程度和什麼有關呢?和之前每次打你都有關!但是各次的貢獻是不一樣的,越早打的巴掌,貢獻越小,所以這就是說,某一時刻的輸出是之前很多次輸入乘以各自的衰減係數之後的疊加而形成某一點的輸出,然後再把不同時刻的輸出點放在一起,形成一個函數,這就是卷積,卷積之後的函數就是你臉上的包的大小隨時間變化的函數。本來你的包幾分鐘就可以消腫,可是如果連續打,幾個小時也消不了腫了,這難道不是一種平滑過程麼?反映到劍橋大學的公式上,f(a)就是第a個巴掌,g(x-a)就是第a個巴掌在x時刻的作用程度,乘起來再疊加就ok了,大家說是不是這個道理呢?我想這個例子已經非常形象了,你對卷積有了更加具體深刻的瞭解了嗎?

作者:Kaixiang Wang
鏈接:https://www.zhihu.com/question/22298352/answer/193852554
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

補充一下@鏡面狐@笑劫戈的答案。

想要形象地理解卷積這個數學概念,那麼思路當然是找它的“實際應用”,最容易想到的例子就是它對動態系統的輸入輸出關係的描述了。許多答主提到了“打臉”的例子,非常形象,就不復述了。

以下略糾結,嫌麻煩可以跳過直接看圖。

之前我對@鏡面狐答案的有部分理解是不準確的;現在看來他對 a 的定義確實有問題(感謝@高啓峯@逐光指出)。順便提一下,@鏡面狐的答案引用了Franklin的那本經典教材,但是我越來越感覺它講卷積的那部分並沒有寫得很清楚,比如它和配圖和文字就對不上號,徒增了理解的難度。我儘量梳理一遍吧。

首先是單位脈衝\delta(t)和單位脈衝響應 h(t) 的定義,大家應該都懂我就不囉嗦了。(注意 \delta(t) 的“面積”爲 1 。)再是定義 p_\Delta(t)h_\Delta(t) ,當 \Delta\rightarrow0 時趨近於 \delta(t)h(t) 。(同樣注意 p_\Delta(t) 的高度爲 \frac{1}{\Delta} ,面積爲 1 。)

一個輸入信號可以拆成很多 p_\Delta(t) 的和,即 u\left(t\right)\approx\cdots+u\left(0\right)p_{\Delta}\left(t\right)\Delta+u\left(\Delta\right)p_{\Delta}\left(t-\Delta\right)\Delta+u\left(2\Delta\right)p_{\Delta}\left(t-2\Delta\right)\Delta+\cdots (所以

@鏡面狐的答案確實少了個 \Delta
輸出即 y\left(t\right)\approx\cdots+u\left(0\right)h_{\Delta}\left(t\right)\Delta+u\left(\Delta\right)h_{\Delta}\left(t-\Delta\right)\Delta+u\left(2\Delta\right)h_{\Delta}\left(t-2\Delta\right)\Delta+\cdots

取極限寫成積分形式即 y\left(t\right)=\int_{-\infty}^{\infty}u\left(\tau\right)h\left(t-\tau\right)d\tau

注意不要忘了 d\tau ,因爲我們是要跟單位脈衝比較面積,即 u(\tau)d\tau1 的多少倍。


糾結部分完。

有了這個基礎,再去理解卷積的公式就沒那麼intimidating了。放張圖,心血來潮隨手畫的,但願能頂個卵用。


另外,對於實際系統(因果系統),由於未來的打臉( \tau>t )不會造成現在的臉腫,所以積分上限設爲 t 就行了;此外我們還一般假設 t=0 之前沒人打臉並且臉也不腫,所以積分下限設爲 0 就行了。因此y(t)=\int^t_0u(\tau)h(t-\tau)d\tau

2、數字圖像處理中卷積

        數字圖像是一個二維的離散信號,對數字圖像做卷積操作其實就是利用卷積核(卷積模板)在圖像上滑動,將圖像點上的像素灰度值與對應的卷積核上的數值相乘,然後將所有相乘後的值相加作爲卷積核中間像素對應的圖像上像素的灰度值,並最終滑動完所有圖像的過程。 




       這張圖可以清晰的表徵出整個卷積過程中一次相乘後相加的結果:該圖片選用3*3的卷積核,卷積核內共有九個數值,所以圖片右上角公式中一共有九行,而每一行都是圖像像素值與卷積核上數值相乘,最終結果-8代替了原圖像中對應位置處的1。這樣沿着圖片一步長爲1滑動,每一個滑動後都一次相乘再相加的工作,我們就可以得到最終的輸出結果。除此之外,卷積核的選擇有一些規則: 
       1)卷積核的大小一般是奇數,這樣的話它是按照中間的像素點中心對稱的,所以卷積核一般都是3x3,5x5或者7x7。有中心了,也有了半徑的稱呼,例如5x5大小的核的半徑就是2。 
       2)卷積核所有的元素之和一般要等於1,這是爲了原始圖像的能量(亮度)守恆。其實也有卷積核元素相加不爲1的情況,下面就會說到。 
        3)如果濾波器矩陣所有元素之和大於1,那麼濾波後的圖像就會比原圖像更亮,反之,如果小於1,那麼得到的圖像就會變暗。如果和爲0,圖像不會變黑,但也會非常暗。 
        4)對於濾波後的結構,可能會出現負數或者大於255的數值。對這種情況,我們將他們直接截斷到0和255之間即可。對於負數,也可以取絕對值。

2.1邊界補充問題

        上面的圖片說明了圖像的卷積操作,但是他也反映出一個問題,如上圖,原始圖片尺寸爲7*7,卷積核的大小爲3*3,當卷積核沿着圖片滑動後只能滑動出一個5*5的圖片出來,這就造成了卷積後的圖片和卷積前的圖片尺寸不一致,這顯然不是我們想要的結果,所以爲了避免這種情況,需要先對原始圖片做邊界填充處理。在上面的情況中,我們需要先把原始圖像填充爲9*9的尺寸。 
常用的區域填充方法包括: 
        圖是我在word裏面畫的,所以有很多回車鍵哈,有些簡陋,大家湊合看吧,意思還是對的,也是爲了畫圖方便,這裏就不用5*5的尺寸了,用3*3定義原始圖像的尺寸,補充爲9*9的尺寸,圖片上的顏色只爲方便觀看,並沒有任何其他含義。 

原始圖像:


2.1.1補零 


2.2.2邊界複製 


2.2.3鏡像


2.2.4塊複製


以上四種邊界補充方法通過看名字和圖片就能理解了,不在多做解釋。

不同卷積核下卷積意義

我們經常能看到的,平滑,模糊,去燥,銳化,邊緣提取等等工作,其實都可以通過卷積操作來完成,下面我們一一舉例說明一下: 
(1)一個沒有任何作用的卷積核: 
這裏寫圖片描述 
將原像素中間像素值乘1,其餘全部乘0,顯然像素值不會發生任何變化。 
(2)平滑均值濾波: 
選擇卷積核: 
這裏寫圖片描述 
該卷積核的作用在於取九個值的平均值代替中間像素值,所以起到的平滑的效果: 

該卷積核的作用在於取九個值的平均值代替中間像素值,所以起到的平滑的效果: 
這裏寫圖片描述 
這裏寫圖片描述

(3)高斯平滑: 
卷積核: 
這裏寫圖片描述 
高斯平滑水平和垂直方向呈現高斯分佈,更突出了中心點在像素平滑後的權重,相比於均值濾波而言,有着更好的平滑效果。 
這裏寫圖片描述 
(4)圖像銳化: 
卷積核: 
這裏寫圖片描述 
該卷積利用的其實是圖像中的邊緣信息有着比周圍像素更高的對比度,而經過卷積之後進一步增強了這種對比度,從而使圖像顯得棱角分明、畫面清晰,起到銳化圖像的效果。 
這裏寫圖片描述 
除了上述卷積核,邊緣銳化還可以選擇: 
這裏寫圖片描述 
(5)梯度Prewitt: 
水平梯度: 
這裏寫圖片描述 
這裏寫圖片描述 
垂直梯度: 
這裏寫圖片描述 
這裏寫圖片描述

梯度Prewitt卷積核與Soble卷積核的選定是類似的,都是對水平邊緣或垂直邊緣有比較好的檢測效果。

(6)Soble邊緣檢測: 
Soble與上述卷積核不同之處在於,Soble更強調了和邊緣相鄰的像素點對邊緣的影響。 
水平梯度: 
這裏寫圖片描述 
這裏寫圖片描述 
垂直梯度: 
這裏寫圖片描述 
這裏寫圖片描述

以上的水平邊緣與垂直邊緣檢測問題可以參考:Soble算子水平和垂直方向導數問題

(7)梯度Laplacian:

卷積核: 
這裏寫圖片描述

這裏寫圖片描述

Laplacian也是一種銳化方法,同時也可以做邊緣檢測,而且邊緣檢測的應用中並不侷限於水平方向或垂直方向,這是Laplacian與soble的區別。下面這張圖可以很好的表徵出二者的區別:來源於OpenCV官方文檔 

這裏寫圖片描述

代碼實現

可以利用OpenCV提供的filter2D函數完成對圖像進行卷積操作,其函數接口爲:

  1. CV_EXPORTS_W void filter2D(
  2. InputArray src,
  3. OutputArray dst,
  4. int ddepth,
  5. InputArray kernel,
  6. Point anchor=Point(-1,-1),
  7. double delta=0,
  8. int borderType=BORDER_DEFAULT );
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

第一個參數: 輸入圖像 
第二個參數: 輸出圖像,和輸入圖像具有相同的尺寸和通道數量 
第三個參數: 目標圖像深度,輸入值爲-1時,目標圖像和原圖像深度保持一致。 
第四個參數: 卷積核,是一個矩陣 
第五個參數:內核的基準點(anchor),其默認值爲(-1,-1)說明位於kernel的中心位置。基準點即kernel中與進行處理的像素點重合的點。 
第六個參數: 在儲存目標圖像前可選的添加到像素的值,默認值爲0 
第七個參數: 像素向外逼近的方法,默認值是BORDER_DEFAULT。

  1. #include <iostream>
  2. #include <iostream>
  3. #include <opencv2/core/core.hpp>
  4. #include <opencv2/highgui/highgui.hpp>
  5. #include <opencv2/imgproc/imgproc.hpp>
  6. using namespace std;
  7. using namespace cv;
  8. int main()
  9. {
  10. Mat srcImage = imread("1.jpg");
  11. namedWindow("srcImage", WINDOW_AUTOSIZE);
  12. imshow("原圖", srcImage);
  13. Mat kernel = (Mat_<double>(3,3) <<
  14. -1, 0 ,1,
  15. -2, 0, 2,
  16. -1, 0, 1);
  17. Mat dstImage;
  18. filter2D(srcImage,dstImage,srcImage.depth(),kernel);
  19. namedWindow("dstImage",WINDOW_AUTOSIZE);
  20. imshow("卷積圖",dstImage);
  21. waitKey(0);
  22. return 0;
  23. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

所以代碼的實現就非常簡單了,不同的卷積操作只需要改變卷積核kernel 即可。




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