컨볼루션 빌드 및 풀링

1. 시작하기 전에

이 Codelab에서는 컨볼루션 및 컴퓨터 비전 시나리오에서 컨볼루션이 강력한 이유를 알아봅니다.

이전 Codelab에서는 패션 아이템의 컴퓨터 비전을 위한 간단한 DNN (Deep Neural Network)을 만들었습니다. 옷을 하나만 착용해야 하고 중앙에 위치해야 했기 때문에 제한되었습니다.

물론 이것이 현실적인 시나리오는 아닙니다. DNN을 통해 사진에 있는 옷을 다른 물체와 식별하거나 의류 앞면 및 중앙에 위치하지 않도록 할 수 있습니다. 이렇게 하려면 컨볼루션을 사용해야 합니다.

기본 요건

이 Codelab에서는 이전 작업인 머신러닝의 '안녕하세요'와 '세계에'를 기반으로 하는 작업컴퓨터 비전 모델 빌드를 기반으로 합니다. 계속하기 전에 Codelab을 완료해 주세요.

학습할 내용

  • 컨볼루션이란?
  • 특성 맵을 만드는 방법
  • 풀링이란?

빌드할 항목

  • 이미지의 특성 지도

필요한 항목

Colab에서 실행되는 나머지 Codelab용 코드를 찾을 수 있습니다.

또한 TensorFlow와 이전 Codelab에 설치한 라이브러리도 필요합니다.

2. 컨볼루션이란 무엇인가요?

컨볼루션은 이미지를 통과하고 처리하며 중요한 특징을 추출하는 필터입니다.

운동화를 착용한 사람의 이미지가 있다고 가정해 보겠습니다. 운동화가 이미지에 포함되어 있는지 어떻게 감지할 수 있나요? 프로그램이 운동화처럼 이미지를 보게 하려면 중요한 기능을 추출하고 필수 기능을 블러 처리해야 합니다. 이를 기능 매핑이라고 합니다.

특성 매핑 프로세스는 이론적으로 간단합니다. 이미지의 모든 픽셀을 스캔한 후 인접한 픽셀을 확인합니다. 이러한 픽셀의 값에 필터의 동등한 가중치를 곱합니다.

예를 들면 다음과 같습니다.

이미지의 컨볼루션

이 경우 3x3 컨볼루션 매트릭스, 즉 이미지 커널이 지정됩니다.

현재 픽셀 값은 192입니다. 인접한 값을 보고 필터에 지정된 값을 곱한 값으로 새 픽셀 값을 최종 값으로 설정하여 새 픽셀 값을 계산할 수 있습니다.

이제 2D 그레이 스케일 이미지에 기본 컨볼루션을 만들어 컨볼루션의 작동 방식을 살펴보겠습니다.

SciPy의 오름차순 이미지를 사용하여 시연할 수 있습니다. 다양한 각도와 선으로 구성된 멋진 기본 제공되는 사진입니다.

3. 코딩 시작

먼저 일부 Python 라이브러리와 오름차순 사진을 가져옵니다.

import cv2
import numpy as np
from scipy import misc
i = misc.ascent()

다음으로 Pyplot 라이브러리 matplotlib를 사용하여 이미지를 그리세요.

import matplotlib.pyplot as plt
plt.grid(False)
plt.gray()
plt.axis('off')
plt.imshow(i)
plt.show()

edb460dd5397f7f4.png

계단의 이미지입니다. 다양한 기능을 분리 및 격리할 수 있습니다. 예를 들어 강한 세로선이 있습니다.

이미지는 NumPy 배열로 저장되므로, 이 배열을 복사하기만 하면 변환된 이미지를 만들 수 있습니다. size_x 및 size_y 변수는 이미지 크기를 유지하므로 나중에 반복할 수 있습니다.

i_transformed = np.copy(i)
size_x = i_transformed.shape[0]
size_y = i_transformed.shape[1]

4. 컨볼루션 행렬 만들기

먼저 컨볼루션 행렬 (또는 커널)을 3x3 배열로 만듭니다.

# This filter detects edges nicely
# It creates a filter that only passes through sharp edges and straight lines. 
# Experiment with different values for fun effects.
#filter = [ [0, 1, 0], [1, -4, 1], [0, 1, 0]] 
# A couple more filters to try for fun!
filter = [ [-1, -2, -1], [0, 0, 0], [1, 2, 1]]
#filter = [ [-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]
 # If all the digits in the filter don't add up to 0 or 1, you 
# should probably do a weight to get it to do so
# so, for example, if your weights are 1,1,1 1,2,1 1,1,1
# They add up to 10, so you would set a weight of .1 if you want to normalize them
weight  = 1

이제 출력 픽셀을 계산합니다. 이미지를 반복하고 1픽셀 여백을 두고 현재 픽셀의 이웃 각각에 필터에 정의된 값을 곱합니다.

즉, 현재 픽셀과 이웃 왼쪽에 있는 픽셀이 이웃 픽셀에 왼쪽 상단 항목을 곱합니다. 그런 다음 결과에 가중치를 곱하고 결과가 0~255 범위 내에 있는지 확인합니다.

마지막으로 변환된 값을 새 값으로 로드합니다.

for x in range(1,size_x-1):
  for y in range(1,size_y-1):
      output_pixel = 0.0
      output_pixel = output_pixel + (i[x - 1, y-1] * filter[0][0])
      output_pixel = output_pixel + (i[x, y-1] * filter[0][1])
      output_pixel = output_pixel + (i[x + 1, y-1] * filter[0][2])
      output_pixel = output_pixel + (i[x-1, y] * filter[1][0])
      output_pixel = output_pixel + (i[x, y] * filter[1][1])
      output_pixel = output_pixel + (i[x+1, y] * filter[1][2])
      output_pixel = output_pixel + (i[x-1, y+1] * filter[2][0])
      output_pixel = output_pixel + (i[x, y+1] * filter[2][1])
      output_pixel = output_pixel + (i[x+1, y+1] * filter[2][2])
      output_pixel = output_pixel * weight
      if(output_pixel<0):
        output_pixel=0
      if(output_pixel>255):
        output_pixel=255
      i_transformed[x, y] = output_pixel

5. 결과 검사

이제 이미지를 표시하여 그 위에 필터를 전달하는 효과를 확인합니다.

# Plot the image. Note the size of the axes -- they are 512 by 512
plt.gray()
plt.grid(False)
plt.imshow(i_transformed)
#plt.axis('off')
plt.show()   

48ff667b2df812ad.png

다음 필터 값과 이러한 값이 이미지에 미치는 영향을 고려하세요.

[-1,0,1,-2,0,2,-1,0,1] 을 사용하면 매우 강력한 수직선 집합을 얻을 수 있습니다.

수직선 필터 감지

[-1,-2,-1,0,0,0,1,2,1] 을 사용하면 가로선이 됩니다.

수평선 감지

다른 값 살펴보기 5x5나 7x7과 같이 다른 크기의 필터도 사용해 보세요.

6. 풀링 이해하기

이제 이미지의 필수 특징을 식별했으므로 어떻게 해야 할까요? 결과 특성 맵을 사용하여 이미지를 분류하려면 어떻게 해야 하나요?

컨볼루션과 마찬가지로 풀링은 특성을 감지하는 데 큰 도움이 됩니다. 풀링 레이어는 존재하는 것으로 감지된 특성을 유지하면서 이미지의 전체 정보를 줄입니다.

여러 유형의 풀링이 있지만 최대 (최대) 풀링이라는 것을 사용해야 합니다.

이미지를 반복하고 각 지점의 픽셀과 바로 이웃을 오른쪽, 아래, 오른쪽 아래로 고려합니다. 최대 크기 (max 풀링)를 가져와 새 이미지로 로드합니다. 따라서 새 이미지는 이전 크기의 4분의 1 크기가 됩니다. 최대 풀링

7. 풀링 코드 작성

다음 코드는 (2, 2) 풀링을 보여줍니다. 이를 실행하여 출력을 확인합니다.

이미지가 원본 크기의 1/4에 불과하지만 모든 특징이 유지되는 것을 확인할 수 있습니다.

new_x = int(size_x/2)
new_y = int(size_y/2)
newImage = np.zeros((new_x, new_y))
for x in range(0, size_x, 2):
  for y in range(0, size_y, 2):
    pixels = []
    pixels.append(i_transformed[x, y])
    pixels.append(i_transformed[x+1, y])
    pixels.append(i_transformed[x, y+1])
    pixels.append(i_transformed[x+1, y+1])
    pixels.sort(reverse=True)
    newImage[int(x/2),int(y/2)] = pixels[0]
 
# Plot the image. Note the size of the axes -- now 256 pixels instead of 512
plt.gray()
plt.grid(False)
plt.imshow(newImage)
#plt.axis('off')
plt.show()

1f5ebdafd1db2595.png

도표의 축을 확인하세요. 이미지가 256x256으로 원래 크기의 4분의 1에 해당하며, 이제 이미지에 포함된 데이터가 줄어들었지만 감지된 특성이 개선되었습니다.

8. 축하합니다

첫 번째 컴퓨터 비전 모델을 빌드했습니다! 컴퓨터 비전 모델을 더욱 향상하는 방법을 알아보려면 컴퓨터 비전을 개선하기 위한 컨볼루셔널 신경망 (CNN) 빌드를 진행하세요.