知識碎片之卷積計算

卷積是一種數學計算核心意義是加權求和其被廣泛的應用於信號處理,聲學,統計學,概論論等衆多領域,在深度學習領域最有名的應用就是卷積神經網絡(CNN),本文中只簡單介紹在卷積神經網絡中應用到的矩陣間卷積運算過程及模式,最終簡單介紹瞭如何通過矩陣間的卷積運算進行邊緣檢測。

矩陣卷積運算

卷積計算
如上所示在兩個矩陣進行卷積運算時,以紅框爲窗口,圖上窗口位置爲運算時窗口的起始位置,每次子運算紅窗口右移一個單位,直到到達右側邊緣後回到最左側然後下移一個單位如此循環直到窗口處於矩陣的右下角,每次取出窗口內的子矩陣與第二個參數矩陣進行對應位相乘然後加和得到的結果依次放入結果矩陣的對應位置。接下來給一個動態的計算過程:
動態過程

三種計算方式

卷積計算有三種運算形式,接下來以下述代碼中定義的矩陣爲例對三種運算形式進行講解:

a = numpy.array([[1,2,4,5],[2,3,4,5],[3,4,5,6],[4,5,6,7]])
Out[52]: 
array([[1, 2, 4, 5],
       [2, 3, 4, 5],
       [3, 4, 5, 6],
       [4, 5, 6, 7]])
b = numpy.array([[1,2,3],[-1,-2,3],[4,-3,-1]])
Out[53]: 
array([[ 1,  2,  3],
       [-1, -2,  3],
       [ 4, -3, -1]])

將要涉及到的數學符號表:

  • HH:第一個參數矩陣的高
  • WW:第一個參數矩陣的寬
  • ff:核矩陣的邊長
  • SS:步長
  • pp:填充

valid:當filter或者說kernel全覆蓋遍歷第一個矩陣參數

  • 原理:最基本的計算
    在這裏插入圖片描述
    圖片來源

  • 尺寸變化
    (HW)(ff)=((Hf)S+1)((Wf)S+1)(H·W)*(f·f)=(\frac {(H-f)}S+1)·(\frac {(W-f)}S+1)
    其中SS爲步長。

  • 代碼實現


signal.convolve2d(a,b,mode='valid')
Out[56]: 
array([[27, 30],
       [29, 35]])
  • 缺點
    • 這種方式處理圖片,圖片的尺寸會變小
    • 邊緣像素點只使用了一次而中間的像素點使用了很多次

same:filter或者說kernel的中心元素遍歷第一個矩陣參數的每個元素

  • 原理:爲了解決valid方法中圖片尺寸及邊緣像素參與計算次數少的問題,same方法首先對圖片進行像素點填充
    在這裏插入圖片描述
    圖片來源

  • 尺寸變化
    ((H+2p)(W+2p))(ff)=HWp=fS+(S1)n2 ((H+2p)·(W+2p))*(f·f)=H·W\\ p =\frac {f-S+(S-1)·n}2
    pp爲邊緣像素填充數量且ff一般爲奇數,SS爲步長。

  • 代碼實現


signal.convolve2d(a,b,mode='same')
Out[55]: 
array([[  3,  11,  15,  24],
       [  8,  27,  30,  10],
       [  9,  29,  35,  16],
       [ -6,   1,   1, -19]])

full:filter或者說kernel的右下角遍歷第一個矩陣參數的每個元素

在這裏插入圖片描述
圖片來源

signal.convolve2d(a,b,mode='full')
Out[54]: 
array([[  1,   4,  11,  19,  22,  15],
       [  1,   3,  11,  15,  24,  30],
       [  5,   8,  27,  30,  10,  28],
       [  9,   9,  29,  35,  16,  34],
       [  8,  -6,   1,   1, -19,  15],
       [ 16,   8,   5,   5, -27,  -7]])

各參數關係如下圖所示:
關係

實際應用:邊緣檢測

原理如下圖所示:
卷積
上圖來自吳恩達CNN教學
代碼如下:

from PIL import Image
from scipy import signal
import numpy as np
I = Image.open(r"C:\Users\myalie\Downloads\timg.jpg")
L = I.convert("L")
L.show()
kernel1 = [[1,0,-1],[1,0,-1],[1,0,-1]]
kernel2 = [[1,1,1],[0,0,0],[-1,-1,-1]]
m = np.asarray(L)
IM1 = Image.fromarray(signal.convolve2d(m,kernel1,mode='valid'))
IM2 = Image.fromarray(signal.convolve2d(m,kernel2,mode='valid'))
IM1.show()
IM2.show()

實例圖:
在這裏插入圖片描述

縱向邊緣檢測:
IM1
橫向邊緣檢測
IM2

RGB模式下的邊緣檢測
代碼如下:

from PIL import Image
from scipy import signal
import numpy as np
I = Image.open(r"C:\Users\myalie\Downloads\timg.jpg")
kernel = [[1,0,-1],[1,0,-1],[1,0,-1]]
final = []
for i in range(3):
    tmp = np.asarray(I.getchannel(i))
    final.append(signal.convolve2d(tmp,kernel,mode='valid'))

Image.merge("RGB",[Image.fromarray(np.array(np.uint8(final[i])))for i in range(3)])

檢測結果如下:
在這裏插入圖片描述

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