Convolution 구현해보기

먼저, 3x3 필터를 정의합니다. 어디선가 많이 보셨을 법한 필터입니다.(가로선을 검출하는)

filter = [[-1, 0, 1], 
        [-2, 0, 2], 
        [-1, 0, 1]]

 

벡터화(Vectorization)을 수행하지 않는 컨볼루션의 구현은 매우 간단합니다. for-loop 2개로 구현할 수 있습니다.

컨볼루션은 이미지의 영역과 컨볼루션 필터를 element-wise 곱한 뒤, 전부 합칩니다. 다음 코드를 보면 알 수 있습니다.
패딩을 사용하지 않기 때문에 시작 지점은 이미지의 (1, 1) 좌표입니다.

x_shape = img.shape[0]
y_shape = img.shape[1]

for x in range(1,x_shape-1):
  for y in range(1,y_shape-1):
      convolution = 0.0
      convolution = convolution + (img[x - 1, y-1] * filter[0][0])
      convolution = convolution + (img[x, y-1] * filter[0][1])
      convolution = convolution + (img[x + 1, y-1] * filter[0][2])
      convolution = convolution + (img[x-1, y] * filter[1][0])
      convolution = convolution + (img[x, y] * filter[1][1])
      convolution = convolution + (img[x+1, y] * filter[1][2])
      convolution = convolution + (img[x-1, y+1] * filter[2][0])
      convolution = convolution + (img[x, y+1] * filter[2][1])
      convolution = convolution + (img[x+1, y+1] * filter[2][2])

      if(convolution < 0):
        convolution = 0
      elif(convolution > 255):
        convolution = 255
  • x_shape와 y_shape는 이미지의 크기를 나타냅니다.
  • for-loop 끝의 if문은 이미지 값의 범위 0 ~ 255를 위해 사용합니다.
  • 아래 테이블에서 위의 코드를 좀 더 편하게 볼 수 있습니다.
img[x-1, y-1] * filter[0][0] img[x, y-1] * filter[0][1] img[x+1, y-1] * filter[0][2]
img[x-1, y] * filter[1][0] img[x, y] * filter[1][1] img[x+1, y] * filter[1][2]
img[x-1, y+1] * filter[2][0] img[x, y+1] * filter[2][1] img[x+1, y+1] * filter[2][2]

 

MaxPooling 구현해보기

흔히 사용하는 (2,2)의 MaxPooling을 구현해보도록 합니다.

new_x_shape = int(x_shape / 2)
new_y_shape = int(y_shape / 2)

# 풀링이 적용될 이미지를 만듭니다.
pooled_img = np.zeros((new_x_shape, new_y_shape))

# 2는 stride를 나타냅니다.
for x in range(0, x_shape, 2):
	for y in range(0, y_shape, 2):
    	pixels = []
        pixels.append(img[x, y])
        pixels.append(img[x + 1, y])
        pixels.append(img[x, y + 1])
        pixels.append(img[x + 1, y + 1])
        # 최댓값만 저장합니다.
        pooled_img[int(x/2), int(y/2)] = max(pixels)
img[x, y] img[x + 1, y]
img[x, y + 1] img[x + 1, y + 1]