11장. Canny 와 Edge 비교
Canny 의 네 단계 한눈에
김장 배추를 다듬는 순서를 떠올려 봅시다. 먼저 흙을 털고, 상한 잎을 고르고, 가장 실한 잎만 남기고, 마지막으로 줄기에 붙은 잎만 묶습니다. 순서를 바꾸면 일이 꼬입니다. Canny 도 정해진 네 단계를 차례로 거칩니다.
그림을 왼쪽부터 읽습니다. 1단계 블러로 노이즈를 줄이고, 2단계에서 칸마다 기울기의 크기와 방향을 재고, 3단계 비최대 억제로 두꺼운 선을 한 줄로 깎고, 4단계 이력 임계값으로 확실한 선과 거기에 이어진 선만 남깁니다. 여기서 흙 털기가 블러, 잎마다 상태 보기가 기울기 재기, 실한 잎만 남기기가 비최대 억제, 줄기에 붙은 잎만 묶기가 이력 임계값입니다.
도형 그림이 네 단계를 거치며 바뀌는 모습입니다. 둘째 칸의 기울기 크기는 테두리를 따라 밝은 띠로 나타나는데, 띠가 몇 칸 두께로 퍼져 있습니다. 셋째 칸의 비최대 억제는 그 띠를 한 줄로 깎았지만 아주 약한 선까지 남아 있고, 넷째 칸의 최종 결과는 기준을 넘은 선만 남겨 깔끔합니다.
네 단계 견주기
| 단계 | 하는 일 | 들어가는 것 | 나오는 것 | 정하는 숫자 |
|---|---|---|---|---|
| 1. 블러 | 노이즈 줄이기 | 흑백 그림 | 부드러워진 그림 | 블러 크기(cv2.Canny 밖에서 직접) |
| 2. 기울기 | 크기와 방향 재기 | 부드러워진 그림 | 칸마다 크기·방향 | apertureSize, L2gradient |
| 3. 비최대 억제 | 꼭대기만 남기기 | 크기·방향 | 한 줄로 깎인 크기 | 없음 |
| 4. 이력 임계값 | 이어진 선만 살리기 | 깎인 크기 | 0 과 255 의 경계 그림 | threshold1, threshold2 |
짧은 예시
import cv2
gray = cv2.imread("ch11_set/shapes.png", cv2.IMREAD_GRAYSCALE)
# 1단계는 cv2.Canny 안에 들어 있지 않아 직접 한다. 6차시의 가우시안 블러
blur = cv2.GaussianBlur(gray, (5, 5), 0)
# 2~4단계는 cv2.Canny 한 줄이 모두 한다
edges = cv2.Canny(blur, 50, 150)
print("결과의 모양:", edges.shape, "/ 값의 종류:", sorted(set(edges.ravel().tolist())))
# 결과: (240, 320), 값은 0 과 255 두 가지cv2.Canny 의 결과는 8장의 이진 그림과 같은 꼴입니다. 경계 칸은 255, 나머지는 0 입니다.
주의할 점
- OpenCV 의
cv2.Canny는 블러를 해 주지 않습니다. 노이즈가 있는 그림은cv2.GaussianBlur를 먼저 걸고 넣습니다. 블러 크기는 실습 4에서 견줘 봅니다. - 네 단계 가운데 우리가 숫자로 정하는 것은 블러 크기, 두 기준값, apertureSize, L2gradient 다섯 가지뿐입니다.