Thresholding
스레시홀딩은 바이너리 이미지를 만드는 가장 대표적인 방법입니다. 바이너리 이미지(binary image)란 검은색과 흰색만으로 표현한 이미지를 의미합니다. 스레시홀딩이란 여러 값을 어떤 임계점을 기준으로 두 가지 부류로 나누는 방법을 의미합니다.
img: 변환할 이미지
threshold: 스레시홀딩 임계값
value: 임계값 기준에 만족하는 픽셀에 적용할 값
type_flag: 스레시홀딩 적용 방법 - 설명은 밑에
ret, out = cv2.threshold(img, threshold, value, type_flag)
cv2.THRESH_BINARY: 픽셀 값이 임계값을 넘으면 value로 지정하고, 넘지 못하면 0으로 지정
cv2.THRESH_BINARY_INV: cv.THRESH_BINARY의 반대
cv2.THRESH_TRUNC: 픽셀 값이 임계값을 넘으면 value로 지정하고, 넘지 못하면 원래 값 유지
cv2.THRESH_TOZERO: 픽셀 값이 임계값을 넘으면 원래 값 유지, 넘지 못하면 0으로 지정
cv2.THRESH_TOZERO_INV: cv2.THRESH_TOZERO의 반대
오츠의 이진화 알고리즘
바이너리 이미지를 만들 때 가장 중요한 점은 임계값을 얼마로 정하냐 하는 것입니다.
1979년 오츠 노부유키는 반복적인 시도 없이 한 번에 임계값을 찾을 수 있는 방법을 찾아냈습니다.
이것이 바로 오츠의 이진화 알고리즘(Otsu's binarization method)입니다.
오츠의 알고리즘은 임계값을 임의로 정해 픽셀을 두 부류로 나누고 두 부류의 명암 분포를 구하는 작업을 반복합니다.
모든 경우의 수 중에서 두 부류의 명암 분포가 가장 균일할 때의 임계값을 선택합니다.
t, t_otsu = cv2.threshold(img, -1, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
print('otsu threshold:', t)
Adaptive Thresholding
위에서 설명한 스레시홀딩이 매번 좋은 성능을 내는 것은 아닙니다.
원본 이미지에서 조명이 일정하지 않거나 배경색이 여러 개인 경우에는 하나의 임계값으로 선명한 바이너리 이미지를 만들어내기 힘들 수도 있습니다.
이때는 이미지를 여러 영역으로 나눈 뒤, 그 주변 픽셀 값만 활용하여 임계값을 구해야 하는데, 이를 적응형 스레시홀딩(Adaptive Thresholding)이라고 합니다.
img: 입력영상
value: 임계값을 만족하는 픽셀에 적용할 값
method: 임계값 결정 방법 설명은 밑에
type_flag: 스레시홀딩 적용 방법 (cv2.threshod()와 동일)
block_size: 영역으로 나눌 이웃의 크기(n x n), 홀수
C: 계산된 임계값 결과에서 가감할 상수(음수 가능)
cv2.adaptiveThreshold(img, value, method, type_flag, block_size, C)
cv2.ADAPTIVE_THRESH_MEAN_C: 이웃 픽셀의 평균으로 결정
cv2.ADAPTIVE_THRESH_GAUSSIAN_C: 가우시안 분포에 따른 가중치의 합으로 결정
대부분의 이미지는 그림자가 있거나 조명 차이가 있습니다. 따라서 전역 스레시홀딩보다 적응형 스레시홀딩을 더 많이 사용합니다.