11장. Canny 와 Edge 비교
기준값 자동으로 정하기
처음 가는 식당에서 메뉴를 고르기 어려우면 "가게에서 가장 많이 팔리는 것"을 시킵니다. 늘 정답은 아니지만 크게 실패하지 않는 고르는 법입니다. 사진이 수백 장이면 장마다 기준값을 손으로 고를 수 없으므로, 그림의 밝기에서 기준값을 계산해 내는 경험 규칙을 씁니다.
그림의 두 상자가 인터넷 예제에 흔한 두 규칙입니다. 초록 상자의 중앙값 규칙은 그림 밝기의 중앙값에 0.67 과 1.33 을 곱해 low 와 high 로 씁니다. 다홍 상자의 Otsu 규칙은 8장의 Otsu 가 고른 값을 high 로, 그 절반을 low 로 씁니다. 여기서 "많이 팔리는 메뉴"가 밝기의 중앙값이나 Otsu 값이고, 그것으로 고른 메뉴가 기준값입니다.
두 규칙 견주기
| 견줄 것 | 중앙값 규칙 | Otsu 규칙 |
|---|---|---|
| low | 0.67 × 중앙값 | 0.5 × Otsu 값 |
| high | 1.33 × 중앙값 | Otsu 값 |
| 바탕이 밝은 그림(중앙값 176) | low 117, high 234 | Otsu 110 이면 low 55, high 110 |
| 생각할 점 | 바탕이 어두우면 기준값이 아주 낮아진다 | 물체와 바탕의 밝기 차이를 본다 |
손으로 계산해 보기
도형 그림의 밝기 중앙값이 176 일 때 중앙값 규칙입니다.
| 할 일 | 식 | 계산 | 결과 |
|---|---|---|---|
| low | 0.67 × 중앙값 | 0.67 × 176 = 117.92 | 117 |
| high | 1.33 × 중앙값 | 1.33 × 176 = 234.08 | 234 |
0.67 과 1.33 은 중앙값에서 33% 아래와 위라는 뜻입니다. 이 33% 라는 숫자도 경험으로 정한 값이라, 그림에 따라 0.2 나 0.5 로 바꿔 씁니다.
짧은 예시
import cv2
import numpy as np
gray = cv2.imread("ch11_set/shapes.png", cv2.IMREAD_GRAYSCALE)
# 중앙값 규칙: np.median 은 모든 칸의 밝기를 늘어놓은 한가운데 값
med = float(np.median(gray))
low_m, high_m = int(0.67 * med), int(1.33 * med)
# Otsu 규칙: 8차시의 THRESH_OTSU 가 고른 값을 high 로, 절반을 low 로
otsu, _ = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
low_o, high_o = int(0.5 * otsu), int(otsu)
print("중앙값", med, "→ low", low_m, "high", high_m)
print("Otsu", int(otsu), "→ low", low_o, "high", high_o)교안 PC 에서는 중앙값 176.0 → low 117, high 234, Otsu 110 → low 55, high 110 이 나옵니다. 같은 그림인데 두 규칙의 기준값이 두 배쯤 차이 납니다.
주의할 점
- 두 규칙 모두 이론으로 증명된 것이 아닌 경험 규칙입니다. 어떤 그림에서는 손으로 고른 값보다 나쁩니다. 실습 5에서 정답 경계로 견줘 봅니다.
- 중앙값 규칙은 바탕의 밝기를 보는 것이지 경계의 세기를 보는 것이 아닙니다. 어두운 바탕에 밝은 글자가 있는 그림이면 기준값이 아주 낮아져 노이즈까지 경계로 잡힙니다.