본문 바로가기

문돌이 존버/카카오 챗봇 스터디

Opencv grayscale, binary, blurring, morphology 전처리 방법 간단 설명!

반응형

오늘은 지난 번 AWS Ubuntu 18.04 서버에 opencv와 tesseract 설치 방법에 이어 tesseract의 OCR 기능 향상을 위해 이미지 전처리 방법을 알아보겠습니다. 말씀드렸듯이 저도 이미지 부분이 낯설어서 이해한대로 최대한 쉽게 설명하려고 합니다.

1. Grayscale image: BGR(blue + green + red)을 GRAY로 색상을 바꾸는 작업

def get_grayscale(image):
    return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

이미지 전처리에서 가장 기본이 되는 작업인 듯 하네요. 컴퓨터에서 이미지를 나타낼 때 (픽셀 x 픽셀 x 채널 수)의 포맷을 사용하는데, 이때 채널 수가 바로 색상을 의미합니다. 따라서 BGR은 채널 수가 3이 되겠고, GRAY로 바꾸면 1이 되겠죠. 

grayscale은 픽셀당 8bit, 즉 256단계의 명암을 표현할 수 있는 이미지라고 합니다. colorimage는 채널이 3개니까 픽셀당 24bit로 표현된다는 것을 알 수 있습니다. opencv에서는 Blue->(255, 0, 0) / Green->(0, 255, 0) / Red->(0, 0, 255) / White->(255, 255, 255) / Black->(0, 0, 0) 으로 표현됩니다. 

2. Binary image: grayscale로 변환한 이미지를 흑백(이진화) 이미지로 바꾸는 작업

def thresholding(image):
    return cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

이진화 처리는 기준이 되는 임계값을 설정하여 이보다 크면 백, 작으면 흑이 되는 방식이라 사용자가 임계값을 잘 결정해야 합니다. 아래는 threshold() 함수의 파라미터 설명입니다.  

cv2.threshold(src, thresh, maxval, type) → retval, dst

# argument 설명
thresh: 사용자가 정한 임계값(픽셀값 분류)
maxval: cv2.THRESH_BINARY나 cv.THRESH_BINARY_INV의 경우 사용하는 최댓값(보통 255로 지정, 픽셀값이 임계값보다 클 경우나 작을 경우 주어진 값을 나타냄)
type: 임계값 함수 동작 지정(타입에 따라 서로 다른 임계값 제공)

retval: 사용된 임계값
dst: 결과 이미지

thresholding type으로는 총 6가지가 있는데요, 자세한 정보를 공부하고 싶으신 분들은 공식문서한글로 번역된 사이트를 참고하시기 바랍니다.

파라미터로는 THRESH_BINARYTHRESH_OTSU가 적혀있는데 보통 이렇게 같이 셋트로 사용되는 듯 합니다. OTSU는 Otus's binarization이라고 불리는 것으로 히스토그램이 2개의 피크를 가지는 이미지, 즉 이항 이미지의 임계값을 자동으로 계산해주는 역할을 합니다. 이때 임계값은 대략 피크들 중간에 있는 값을 선택합니다. 

3. Blur 처리: 이미지의 노이즈를 제거하는 작업

이미지에 커널(마스크 또는 필터라고 부르기도 함)을 컨볼루션(convolution)하여 블러링(blurring), 샤프닝(sharpening) 할 수 있습니다. 커널 크기는 보통 홀수로 하는데, 그 이유는 패딩(padding)을 추가하는 작업에서 계산하는데 편하게 하기 위함입니다. 

# 평균 블러링(Average Blurring)
# 모든 픽셀에 동일한 가중치 부여
def avg_blur(image, kernel_size=(5,5)):
    return cv2.blur(image, kernel_size)

# 가우시안 블러링(Gaussian Blurring)
# 중심에 있는 픽셀에 높은 가중치 부여
def gau_blur(image, kernel_size=(5,5)):
   return cv2.GaussianBlur(image, kernel_size, 0)

# 미디언 블러링(Median Blurring)
# 커널 크기 내 픽셀을 크기 순으로 정렬 후 중간값을 뽑아 픽셀로 사용
def median_blur(image, kernel_size=5):
    return cv2.medianBlur(image, ksize=kernel_size)

직관적으로 커널 사이즈를 크게 하면 이미지가 전체적으로 블러링해진다는 것을 알 수 있겠죠. 

4. Morphology 변환: 이미지의 특정 부분을 조건에 맞춰 변환하는 작업

모폴로지 변환(Morphology transformation)은 특정 부분을 단순화하거나 제거, 보정하는 것을 의미합니다. 보통 binary 이미지나 grayscale 이미지에서 흰색으로 표현된 객체의 형태를 개선하기 위해서 사용된다고 하네요. 

# Dilation(팽창)
# 객체 외곽 픽셀 주변에 1(흰색) 추가 -> 이미지 경계를 기준으로 팽창하는 효과 발생
def delation(image):
    kernel = np.ones((5,5), np.unit8)
    result = cv2.dilate(image, kernel, iterations=1)
    return result
    
# Erosion(침식)
# 객체 외곽 픽셀 주변에 0(검은색) 추가 -> 이미지 경계를 기준으로 침식하는 효과 발생
def erosion(image):
    kernel = np.ones((5,5), np.uint8)
    result = cv2.erode(image, kernel, iterations=1)
    return result 
    
# Opening(침식 -> 팽창)
# 이미지 상의 작은 잡티, 물체 등을 제거하는 효과 발생
def open(image):
    kernel = np.ones((5,5), np.uint8)
    result = cv2.morphologyEx(image, cv.MORPH_OPEN, kernel)
    return result
    
# Closing(팽창 -> 침식)
# 전체적인 윤곽을 뚜렷하게 보이는 효과 발생
def close(image):
    kernel = np.ones((5,5), np.unit8)
    result = cv2.morphologyEx(image, cv.MORPH_CLOSE, kernel)
    return result

사용한 커널 크기나 반복 횟수를 조정한다면 객체 외곽 픽셀이 1 또는 0이 되는 정도가 달라질 수 있습니다. 

참고 블로그:

- turtle-dennis.tistory.com/31?category=843819

- webnautes.tistory.com/1270?category=756330webnautes.tistory.com/1257?category=756330

728x90
반응형