OpenCV를 활용한 디지털 Digits 분석하기!!(1)

프로젝트 관련으로 OCR을 구현해야 했습니다. Tesseract 등 많은 OCR 툴이 있었는데, 제가 읽어야 하는 값은 디지털 Digits 형식으로서, 다른 방식으로도 되지 않을까 라는 의문이 들어 디지털 Digits용으로 구현해봤습니다.


1. Warping

original

위의 사진에서 알고자 하는 값은 0.4, 20.4의 숫자들입니다. 보시다시피 우측면에서 촬영한 사진으로 제대로 하기 위해선 전처리 과정이 필요할 것으로 보입니다.

우선 우리가 알고자 하는 영역을 추출하여 사각형 비율로 변환하는 작업을 해보도록 합시다.

이를 Warping이라고 하는데 왜곡된 이미지를 정규화하는 겁니다.

우선 그림판 등을 이용해서 우리가 Warping 하고자 하는 영역의 픽셀값을 얻도록 하겠습니다.

import cv2
import numpy as np

img = cv2.imread('orginal.jpg')
upper_point = np.float32([[265, 32], [256, 129], [375, 51], [367, 142]])
lower_point = np.float32([[207, 215], [195, 310], [370, 207], [361, 290]])

#변환 후 points(직사각형으로 구현)
points = np.float32([[10, 10], [10, 100], [200, 10], [200, 100]])

#변환 matrix 계산
upper_m = cv2.getPerspectiveTransform(upper_point, points)
lower_m = cv2.getPerspectiveTransform(lower_point, points)

#warping된 이미지(210X110픽셀)
upper_pic = cv2.warpPerspective(img, upper_m, (210,110))
lower_pic = cv2.warpPerspective(img, lower_m, (210,110))

위의 코드를 이용하여 warping 된 이미지는 다음과 같습니다.

upper

lower

자, 이제 이 사진들을 이용하여 숫자를 읽어보도록 하겠습니다.

2. 전처리(1)

임계점 처리를 위해서 이미지는 흑백으로 하겠습니다.

gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)를 이용하여 변환하세요.

이미지의 전처리는 크게 선명하게 혹은 희미하게로 나눌 수 있습니다.

OpenCV의 filter2D method를 이용하여 선명하게 해봅시다.

kernel = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]])
sharpen = cv2.filter2D(img, -1, kernel)

sharpen_upper

sharpen_lower

OpenCV의 GaussianBlur method를 이용하여 흐릿하게 해봅시다.

blurred = cv2.GaussianBlur(img, (5,5), 0)

(3, 3)은 blur kernel size로서 값이 같을 필요는 없지만 양의 홀수를 넣어야합니다. 값이 커질 수록 흐릿해지는 정도가 커집니다.

blur_upper

blur_lower

우리가 가진 이미지는 약간 흐릿한 이미지에 가까우므로 sharpen 과정만 거치고 다음으로 넘어가겠습니다.

3. 전처리(2)

우선 기본적인 Threshold부터 해보겠습니다.

thresh = cv2.threshold(sharpen, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

cv2.THRESH_OTSU flag는 임계값의 자동 계산을 위해서 넣어줍니다.

결과는 다음과 같습니다.

thresh_upper

thresh_lower

결과가 처참하군요. 나쁜 말 나쁜 말

비슷한 색상으로 이루어진 이미지라 이런 결과가 나온 것으로 판단됩니다. 그렇다면 이제 하나의 임계값으로 전체 이미지 영역을 처리하는 게 아니라 영역별 Thresholding을 하는 AdaptiveThreshold을 이용하도록 하겠습니다.

adap_thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 25, 5)

뒤의 BlockSize(25), Constant(5)는 알맞게 변경하시면 됩니다.

adThresh_upper

adThresh_lower

결과가 괜찮네요!착한 말 착한 말


  • 지금까지 분석용 이미지 전처리를 마쳤습니다.

  • 다음 시간에 본격적으로 전처리된 이미지로 해당 숫자를 분석해보도록 합시다!!


Reference