8장. Threshold, Adaptive Threshold, Otsu
임계값을 고르는 어려움
커트라인을 너무 낮게 잡으면 거의 모두 합격하고, 너무 높게 잡으면 거의 모두 떨어집니다. 시험 점수 분포를 그려 보니 "잘한 무리"와 "못한 무리"가 두 언덕으로 뚜렷이 나뉘어 있다면, 두 언덕 사이의 낮은 곳에 커트라인을 두는 것이 가장 자연스럽습니다.
위의 막대는 4장에서 배운 히스토그램으로, 밝기를 8 씩 묶은 32개 구간으로 그렸습니다. 왼쪽 봉우리(60~110)가 부품, 오른쪽 봉우리(180~210)가 작업대입니다. 갈색 선 70 은 부품 봉우리 한가운데라 와셔와 짙은 동전 하나만 검게 남고, 다홍 선 195 는 작업대 봉우리 한가운데라 작업대의 왼쪽 위 절반까지 검게 칠해집니다. 초록 선 136 처럼 두 봉우리 사이의 골짜기에 두면 부품만 깨끗하게 나뉩니다. 여기서 두 언덕이 두 봉우리이고, 언덕 사이 낮은 곳이 골짜기입니다.
임계값이 어긋날 때
| 임계값 | 결과 | 부품 그림에서 |
|---|---|---|
| 너무 낮다 | 물체의 밝은 부분까지 바탕(흰색)으로 간다 | 70: 동전 대부분이 사라진다 |
| 골짜기 | 물체와 바탕이 깨끗이 나뉜다 | 136: 부품만 검게 남는다 |
| 너무 높다 | 바탕의 어두운 부분까지 물체(검정)로 간다 | 195: 작업대가 비스듬히 반쯤 검어진다 |
195 에서 작업대가 비스듬히 갈리는 것은 작업대 밝기가 왼쪽 위 184 에서 오른쪽 아래 206 쯤까지 조금씩 바뀌도록 만들었기 때문입니다. 커트라인이 봉우리 안에 있으면 이런 작은 밝기 차이가 그대로 드러납니다.
짧은 예시
import cv2
gray = cv2.imread("ch08_parts.png", cv2.IMREAD_GRAYSCALE)
for t in [70, 136, 195]:
_, out = cv2.threshold(gray, t, 255, cv2.THRESH_BINARY)
# 검정(0) 칸의 비율: 부품으로 본 칸이 그림의 몇 할인가
black = round(float((out == 0).mean()), 3)
print(f"임계값 {t}: 검정 칸 비율 {black}")교안 PC 에서는 70 에서 0.063, 136 에서 0.176, 195 에서 0.662 가 나옵니다. 골짜기의 어디에 두든 거의 같습니다. 110 이면 0.173, 180 이면 0.182 입니다. 골짜기에는 칸이 거의 없기 때문입니다.
주의할 점
- 골짜기는 히스토그램을 그려 눈으로 찾을 수 있지만, 사진이 수백 장이면 일일이 볼 수 없습니다. 뒤에서 볼 Otsu 가 이 일을 자동으로 합니다.
- 실제 사진의 히스토그램은 이 그림처럼 봉우리가 또렷하지 않을 때가 많습니다. 봉우리가 하나뿐이거나 셋 이상이면 골짜기가 애매합니다.