9장. Morphology: 침식, 팽창, 열기, 닫기
그 밖의 모폴로지 연산
사진 두 장을 겹쳐 놓고 "틀린 그림 찾기"를 하면 달라진 곳만 눈에 들어옵니다. 모폴로지에도 두 결과를 빼서 바뀐 곳만 남기는 연산이 있습니다. 팽창에서 침식을 빼면 테두리만, 원본에서 열기를 빼면 열기가 지운 작은 흰 것만, 닫기에서 원본을 빼면 닫기가 메운 작은 구멍만 남습니다.
세 상자가 이 절의 세 연산입니다. 초록 상자의 그레이디언트는 팽창 − 침식, 다홍 상자의 탑햇은 원본 − 열기, 보라 상자의 블랙햇은 닫기 − 원본입니다. 여기서 사진 두 장이 두 연산의 결과이고, 틀린 그림 찾기가 빼기입니다.
윗줄의 그레이디언트는 도형과 글자의 테두리만 가는 흰 줄로 남겼습니다. 아랫줄 가운데의 탑햇은 열기가 지운 흰 잡티를 보여 주고, 오른쪽 블랙햇은 닫기가 메운 구멍과 틈을 보여 줍니다. 둘 다 끊긴 획의 짧은 조각이나 획의 좁은 모서리처럼 도장보다 작은 부분도 함께 잡힙니다.
다섯 가지 연산 이름
| 이름 | 상수 | 계산 | 남는 것 |
|---|---|---|---|
| 열기 | cv2.MORPH_OPEN | 침식 → 팽창 | 흰 잡티를 지운 그림 |
| 닫기 | cv2.MORPH_CLOSE | 팽창 → 침식 | 구멍·틈을 메운 그림 |
| 그레이디언트 | cv2.MORPH_GRADIENT | 팽창 − 침식 | 테두리 |
| 탑햇 | cv2.MORPH_TOPHAT | 원본 − 열기 | 도장보다 작은 흰 것 |
| 블랙햇 | cv2.MORPH_BLACKHAT | 닫기 − 원본 | 도장보다 작은 검은 구멍·틈 |
그레이디언트는 침식 절의 8×8 그림에서 손으로도 셀 수 있습니다. 팽창 뒤 흰 칸 47개 가운데 침식 뒤에도 흰 4칸을 빼면 43칸이 테두리로 남습니다.
짧은 예시
import cv2
import numpy as np
img = np.zeros((8, 8), np.uint8)
img[1:5, 1:5] = 255
img[3, 5] = 255
img[6, 6] = 255
se = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
grad = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, se)
# subtract: 칸마다 빼되 0 보다 작으면 0 으로 둔다
by_hand = cv2.subtract(cv2.dilate(img, se), cv2.erode(img, se))
print("테두리 칸:", int((grad == 255).sum()), "/ 손으로 뺀 것과 같은가:", np.array_equal(grad, by_hand))
# 결과: 테두리 칸 43 / 손으로 뺀 것과 같은가: True