CS131 homework1 使用numpy實現卷積

牧空發表於2020-11-21

預備

import numpy as np

def zero_pad(image, pad_height , pad_width):
	H,W = image.shape
	out = None
	### 
    out = np.zeros((H+2*pad_height, W+2*pad_width))
    for i in range(H):
    	for j in range(W):
        	out[i+pad_height,j+pad_width] = image[i,j]
    ### end
    return out

conv_nested

使用最基礎的四重巢狀for迴圈進行計算,分別遍歷圖片和卷積核

def conv_nested(image, kernel):
    Hi, Wi = image.shape
    Hk, Wk = kernel.shape
    out = np.zeros((Hi, Wi))

    ### YOUR CODE HERE
    for m in range(Hi):
        for n in range(Wi):
            for i in range(Hk):
                for j in range(Wk):
                  if(m - i + Hk//2 >= 0 and n - j + Wk//2 >= 0) and (m - i + Hk//2 < Hi and n - j + Wk//2 <Wi):
                    out[m,n] += kernel[i,j] * image[m - i + Hk//2, n - j + Wk//2]
    ### END YOUR CODE

    return out

conv_fast

題目給了提示使用np.flip()np.sum()函式簡化計算,將四重for迴圈減少為兩重,同時也不需要去計算卷積核和圖片在計算時對應的位置

def conv_fast(image, kernel):

    Hi, Wi = image.shape
    Hk, Wk = kernel.shape
    out = np.zeros((Hi, Wi))
    #print(Hi,Wi,Hk,Wk)

    ### YOUR CODE HERE
    pad_img = zero_pad(image,Hk//2,Wk//2)
    #print(pad_img.shape)
    kernel_fliped = np.flip(np.flip(kernel,0),1)
    for m in range(Hi):
      for n in range(Wi):
        out[m,n] = np.sum(pad_img[m: m+Hk, n : n+Wk] * kernel_fliped)
    ### END YOUR CODE

    return out

conv_faster

將pad過後的影像矩陣每次要和卷積核進行元素相乘的部分單獨抽出來作為新矩陣的一行的資料,依次填充得到一個新的矩陣大小為 ( H i ∗ W i , H k ∗ W k ) (H_i*W_i,H_k*W_k) (HiWi,HkWk),然後將卷積核也reshape ( H k ∗ W k , 1 ) (H_k*W_k,1) (HkWk,1),使用矩陣相乘可以大大縮短計算時間。GPU對矩陣計算進行了優化。

def conv_faster(image, kernel):

    Hi, Wi = image.shape
    Hk, Wk = kernel.shape
    out = np.zeros((Hi, Wi))

    ### YOUR CODE HERE
    pad_image = zero_pad(image, Hk//2, Wk//2)
    kernel_filp = np.flip(np.flip(kernel, 0), 1)
    mat = np.zeros((Hi*Wi, Hk*Wk))
    for i in range(Hi*Wi):
        row = i // Wi
        col = i % Wi
        # 將需要計算的卷積核大小的資料填充到第i行
        mat[i, :] = pad_image[row: row+Hk, col: col+Wk].reshape(1, Hk*Wk)
    out = mat.dot(kernel_flip.reshape(Hk*Wk, 1)).reshape(Hi, Wi)
    ### END YOUR CODE

    return out

相關文章