10장. Sobel 과 Laplacian 경계 검출
경계만 남기기와 두 방법 견주기
시험 점수표에서 "80점 넘는 학생만 형광펜으로 칠해 주세요"라고 하면, 점수가 어떻든 칠했는지 안 칠했는지 두 가지로만 남습니다. 기울기의 크기도 0 부터 몇백까지 여러 값이 나오지만, "경계인가 아닌가"로 답하려면 기준 하나를 정해 넘는 칸만 흰색으로 칠합니다. 8장에서 본 임계값(이진화)과 같은 일입니다.
그림의 네 단계를 따라 기울기 크기를 흑백 두 값의 경계 지도로 바꿉니다. 여기서 시험 점수가 기울기의 크기, 80점 커트라인이 기준, 형광펜을 칠한 학생이 경계 칸입니다. 11장의 Canny 는 기준을 두 개 쓰고 선을 가늘게 다듬어, 이 일을 더 똑똑하게 합니다.
기준 100 에서는 모든 도형과 계단 띠의 경계가 남습니다. 기준을 400 으로 올리면 밝기 차이가 30 인 계단 띠의 안쪽 선(크기 120)과, 차이가 90 인 원의 테두리(곧은 쪽 크기 360)가 대부분 사라집니다. 기준은 남기고 싶은 경계가 얼마나 뚜렷한지에 맞춰 고릅니다.
기준을 정하는 법
| 방법 | 하는 일 | 좋은 점과 아쉬운 점 |
|---|---|---|
| 직접 정하기 | 크기 그림을 보고 숫자 하나를 고른다 | 쉽다. 그림마다 다시 골라야 한다 |
| 최댓값의 비율 | 가장 큰 크기의 몇 분의 일을 기준으로 | 밝기가 다른 그림에도 덜 흔들린다 |
| 두 기준 쓰기 | 강한 경계와 약한 경계를 나눠 잇는다 | 11장의 Canny 가 쓰는 방법 |
Sobel 과 Laplacian 견주기
두 상자는 이 장에서 본 두 방법의 결론입니다. Sobel 은 gx, gy 두 장으로 방향까지 알려 주고 노이즈에 덜 흔들립니다. Laplacian 은 한 장으로 끝나 간단하지만 방향이 없고 노이즈에 더 흔들립니다.
| 견줄 것 | Sobel | Laplacian |
|---|---|---|
| 계산 | 한 번 빼기 (+ 1-2-1 무게) | 두 번 빼기 |
| 결과 | gx, gy 두 장 → 크기, 방향 | 한 장 |
| 방향 정보 | 있다 (cv2.phase) | 없다 |
| 경계의 자리 | 크기가 큰 곳 | + 와 − 사이의 0 을 지나는 곳 |
| 노이즈 | 흔들린다 (바탕 0.372) | 더 흔들린다 (바탕 0.591) |
| 어울리는 곳 | 차선처럼 방향이 필요한 일, 크기로 임계값 | 방향과 관계없이 테두리만, 블러와 짝(LoG) |
짧은 예시
import cv2
import numpy as np
img = cv2.imread("ch10_shapes.png", cv2.IMREAD_GRAYSCALE)
mag = cv2.magnitude(cv2.Sobel(img, cv2.CV_64F, 1, 0), cv2.Sobel(img, cv2.CV_64F, 0, 1))
# np.where(조건, 참일 때, 거짓일 때): 크기가 기준을 넘으면 255, 아니면 0
for t in (100, 400):
edges = np.where(mag > t, 255, 0).astype(np.uint8)
print(t, int((edges == 255).sum()))
# 결과: 100 3327 / 400 15938장의 cv2.threshold 로도 같은 일을 할 수 있지만, 이 함수는 uint8 과 32비트 소수(float32)만 받습니다. CV_64F 크기 그림에 쓰려면 mag.astype(np.float32) 로 바꿔 줍니다.
주의할 점
- 크기 그림을
convertScaleAbs로 0~255 에 담은 뒤 임계값을 걸면, 255 넘는 값이 모두 255 로 잘려 강한 경계끼리 구별이 안 됩니다. 기준은CV_64F크기에 바로 겁니다. - 이렇게 얻은 선은 Sobel 의 경계 폭만큼(2칸 이상) 굵습니다. 한 칸 굵기로 다듬는 일은 11장에서 봅니다.