이 글의 원문은 https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html 입니다.
이 글에서는 Simple thresholding, Adaptive thresholding, Otsu’s thresholding 중 처음 2가지에 대해 언급합니다. 그리고 글을 나눠 Otsu’s thresholding을 설명하겠습니다.
Image Thresholding 즉, 이미지의 임계값 처리란 픽셀값(대부분은 Grayscale 값)이 어떤 조건(임계 조건)을 만족할때 해당 픽셀의 값을 어떤 값으로 치환할 것인가를 결정하는 것인데, 먼저 Simple thresholding에 대한 예제를 살펴보면..
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('./data/gray-gradient.jpg', cv2.IMREAD_GRAYSCALE) ret,thresh1 = cv2.threshold(img, 180, 255, cv2.THRESH_BINARY) ret,thresh2 = cv2.threshold(img, 180, 255, cv2.THRESH_BINARY_INV) ret,thresh3 = cv2.threshold(img, 180, 255, cv2.THRESH_TRUNC) ret,thresh4 = cv2.threshold(img, 180, 255, cv2.THRESH_TOZERO) ret,thresh5 = cv2.threshold(img, 180, 255, cv2.THRESH_TOZERO_INV) titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV'] images = [img, thresh1, thresh2, thresh3, thresh4, thresh5] for i in range(6): plt.subplot(2,3,i+1), plt.imshow(images[i], 'gray') plt.title(titles[i]) plt.xticks([]), plt.yticks([]) plt.show()
결과를 먼저 보고 코드에서 중요한 부분을 언급하겠습니다.
Original Image가 입력 이미지인 원본인데, 5개에 대한 Simple thresholding에 대한 결과가 표시되고 있습니다. Simple thresholding 처리에 대한 함수는 cv.threshold 인데, 첫번째 인자는 입력 이미지, 두번째는 조건값에 대한 픽셀값의 최소값, 세번째는 조건값에 대한 픽셀값의 최대값, 네번째는 thresholding 조건에 대한 결과값 처리 방식인데 살펴보면..
- cv2.THRESH_BINARY – 조건을 만족하는 픽셀값을 255로 만족하지 않는 픽셀값을 0으로 설정
- cv2.THRESH_BINARY_INV – 조건을 만족하는 픽셀값을 0로 만족하지 않는 픽셀값을 255으로 설정
- cv2.THRESH_TRUNC – 조건을 만족하는 픽셀값을 255로 만족하지 않는 픽셀값을 원본값으로 설정
- cv2.THRESH_TOZERO – 조건을 만족하는 픽셀값을 원본값으로 만족하지 않는 픽셀값을 0으로 설정
cv2.THRESH_TOZERO_INV – 조건을 만족하는 픽셀값을 0로 만족하지 않는 픽셀값을 원본값으로 설정
이제 다음은 Adaptive thresholding인데요. Simple thresholding의 문제점은 이미지가 전체적으로 동일한 밝기를 가져야 한다는 것인데.. 예를 들어서 하나의 이미지에 어느 부분은 그림자가 들어가 있을 경우 이 그림자 부분에 대한 처리가 제대로 되지 않습니다. 이를 개선하기 위한 방식이 Adaptive thresholding이며 예제 코드는 다음과 같습니다.
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('./data/srcThreshold.png', 0) img = cv2.medianBlur(img, 5) # 잡음제거 ret,th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) th2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2) th3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) titles = ['Original Image', 'Simple Thresholding (v = 127)', 'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding'] images = [img, th1, th2, th3] for i in range(4): plt.subplot(2, 2, i+1), plt.imshow(images[i], 'gray') plt.title(titles[i]) plt.xticks([]), plt.yticks([]) plt.show()
결과를 보면..
총 4개의 영상이 표시되는데 Original Image는 입력 원본 영상, Simple Threshold는 앞서 살펴본 cv2.threshold에 의한 처리 영상입니다. 원본 이미지에서 다른 부분보다 상대적으로 어두운 부분에 대해도 원하는 처리가 된것을 비교해 볼 수 있습니다. 나머지 2개가 Adaptive thresholding인데 첫번째는 단순 평균값, 두번째는 가중치에 의해 처리된 값이 합입니다. 이는 cv.adaptiveThreshold 함수의 세번째 인자에 의해 지정되며 아래와 같습니다.
- cv2.ADAPTIVE_THRESH_MEAN_C – 대상 픽셀값 주위의 픽셀값들의 평균값에 C 값을 더함
- cv2.ADAPTIVE_THRESH_GAUSSIAN_C – Gaussian Window에 의해 가중치 값이 적용된 픽셀값들의 합에 C 값을 더함
cv.adaptiveThreshold의 전체 인자를 살펴보면 첫번째는 입력 이미지, 두번째는 픽셀값의 최대값, 세번째와 네번째는 앞서 설명한 바가 같으며, 다섯번째는 주의값의 픽셀을 얻을 Window의 크기, 여섯번째는 C 값입니다.