2019. 7. 5. 18:00ㆍPython-이론/python-opencv
이미지 Thresholding
이미지 Thresholding는 문턱 값 이상이면 어떤 값으로 바꾸어주고 낮으면 0으로 바꾸어주는 기능을 합니다. 예전에 전자전기개론때 배운 문턱전압이랑 비슷한 이론인 것 같습니다.
cv2.threshold(img, threshold_value, value, flag)
img:grayScale이고 threshold_value는 픽셀 문턱값이고 문턱값 이상이면 value로 바꾸어줍니다.
flag에서도 다양한 종류가 존재합니다.
cv2.THRESH_BINARY: threshold보다 크면 value이고 아니면 0으로 바꾸어 줍니다.
cv2.THRESH_BINARY_INV: threshold보다 크면 0이고 아니면 value로 바꾸어 줍니다.
cv2.THRESH_TRUNC: threshold보다 크면 value로 지정하고 작으면 기존의 값 그대로 사용한다.
cv2.THRESH_TOZERO: treshold_value보다 크면 픽셀 값 그대로 작으면 0으로 할당한다.
cv2.THRESH_TOZERO_INV: threshold_value보다 크면 0으로 작으면 그대로 할당해준다.
import numpy as np
import cv2
def setNamedWindow(windowName, type):
cv2.namedWindow(windowName, type)
def show(windowName, src):
cv2.imshow(windowName, src)
img = cv2.imread("../resource/Images/ipad.jpeg", cv2.IMREAD_GRAYSCALE)
setNamedWindow("original", cv2.WINDOW_NORMAL)
setNamedWindow("BINARY", cv2.WINDOW_NORMAL)
setNamedWindow("BINARY_INV", cv2.WINDOW_NORMAL)
setNamedWindow("TRUNC", cv2.WINDOW_NORMAL)
setNamedWindow("TOZERO", cv2.WINDOW_NORMAL)
setNamedWindow("TOZERO_INV", cv2.WINDOW_NORMAL)
ret, thr1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
ret, thr2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
ret, thr3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
ret, thr4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
ret, thr5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)
show("original", img)
show("BINARY", thr1)
show("BINARY_INV", thr2)
show("TRUNC", thr3)
show("TOZERO", thr4)
show("TOZERO_INV", thr5)
cv2.waitKey(0)
cv2.destroyAllWindows()
결과
Adaptive Thresholding
adaptive thresholding은 앞서 설명한 것과 다르게 지역별로 thresholding 값을 구해줘서 적용시키는 방법입니다. 개발자가 정해준 임의의 값이 아닌 bookSize*bookSize에서 구할 수 있기 때문에 더 정확하게 threshold를 적용할 수 있을 것 같습니다.
코드
import numpy as np
import cv2
img = cv2.imread("../resource/images/ipad.jpeg", cv2.IMREAD_GRAYSCALE)
ret, thr1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
thr2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
thr3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
title = ['original', 'Global Threshold', 'Adaptive Mean', 'Adaptive Gaussian']
images = [img, thr1, thr2, thr3]
for i in range(4):
cv2.namedWindow(title[i], cv2.WINDOW_NORMAL)
cv2.imshow(title[i], images[i])
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.adaptiveThreshold(img, value, adaptiveMethod, thresholdType, blockSize, C)
img: gray 스케일의 값입니다.
value: 문턱 값 이상이되면 사용되는 value입니다.
adaptiveMethod: threshold를 구해주는데 사용되는 알고리즘입니다.
cv2.ADAPTIVE_THRESH_MEAN_C: 적용할 픽셀 (x, y)를 중심으로 하는 bookSize * bookSize안에 있는 픽셀 값의 평균에서 C를 뺀 값입니다.
cv2.ADATPIVE_THRESH_GAUSSIAN_C: 적용할 픽셀 (x, y)를 중심으로 하는 bookSize * bookSize안에 있는 Gaussian 윈도우 기반 가중치들의 합에서 C를 뺀 값입니다.
blockSize: 문턱 값을 계산하기 위한 block크기 입니다. 이는 홀수를 해야합니다. 왜냐하면 픽셀이 블럭의 중앙이 되어야합니다.
C: 보정 상수로 이 값이 양수이면 계산된 adaptive 문턱값에서 빼고 음수이면 더해줍니다.
결과
Otsu's Binarization
global thresholding 방법에서 문턱값으로 우리가 정한 임의의 값을 사용했습니다. 그렇지만 최대의 효율의 T값을 찾아야합니다. 이런 T 값을 찾기 위해서는 Otsu's 이진화 방법이 사용될 수 있습니다. Otsu Binarization은 두개의 봉우리 사이의 값을 선택하여 더 개선되게 이진화를 해줄 수 있습니다. 즉 분산을 최소로 만들어줍니다.
코드
import numpy as np
import cv2
import matplotlib.pyplot as plt
def thresholding():
img = cv2.imread("../resource/Images/ipad.jpeg", cv2.IMREAD_GRAYSCALE)
ret, thr1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
ret, thr2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
blur = cv2.GaussianBlur(img, (5, 5), 0)
ret, thr3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
titles = [
'original', 'Histogram', 'G-Thresholding',
'original', 'Histogram', 'Otsu-Thresholding',
'Gaussian Filter', 'Histogram', 'Otsu-Thresholding'
]
images = [img, 0, thr1, img, 0, thr2, img, 0, thr3]
for i in range(3):
plt.subplot(3, 3, i * 3 + 1), plt.imshow(images[i * 3], 'gray')
plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])
plt.subplot(3, 3, i * 3 + 2), plt.hist(images[i * 3].ravel(), 256)
plt.title(titles[i * 3]), plt.xticks([]), plt.yticks([])
plt.subplot(3, 3, i * 3 + 3), plt.imshow(images[i * 3+2], 'gray')
plt.title(titles[i * 3+2]), plt.xticks([]), plt.yticks([])
plt.show()
thresholding()
ret, thr2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.THRESH_BINARY + cv2.THRESH_OTSU
cv2.에서는 Otsu Binarization을 적용하는 함수는 따로 없고, cv2.threshold() 함수에 cv2.THRESH_BINARY + cv2.THRESH_OTSU 더하고 문턱값에 0을 전달해주면 됩니다. 이렇게 하면 cv2.threshold() 함수는 적절한 문턱값을 계산한 후 이를 적용한 결과를 리턴합니다.
blur = cv2.GaussianBlur(img, (5, 5), 0)
GaussianBlur를 사용하여 노이즈를 제거하여 이미지를 바꾸어 주었습니다.
plt.subplot(3, 3, 3*i+1), plt.imshow(images[i*3], 'gray')
matplotlib을 통해 view를 만들어 주었습니다.
결과
'Python-이론 > python-opencv' 카테고리의 다른 글
[opencv-python] blurring (1) | 2019.07.07 |
---|---|
[opencv-python] 이미지 변화주기 (0) | 2019.07.06 |
[opencv-python] 색공간 바꾸기 및 색 추적 (2) | 2019.07.04 |
[opencv-python] 이미지 연산 처리를 이용한 합성 (0) | 2019.07.02 |
[opencv-python] roi 및 속성, 채널 (0) | 2019.07.02 |