9장. Morphology: 침식, 팽창, 열기, 닫기
닫기
낡은 바지의 작은 구멍을 다리미로 붙이는 수선 테이프로 메우는 장면을 떠올려 봅시다. 테이프를 구멍보다 조금 넓게 붙인 뒤, 삐져나온 가장자리를 가위로 다듬어 바지의 원래 모양에 맞춥니다. 닫기는 팽창으로 구멍과 틈을 메운 뒤, 같은 도장으로 침식해 굵어진 획을 원래 굵기로 되돌립니다.
그림의 세 단계가 닫기의 순서입니다. 팽창에서 도장보다 작은 틈과 구멍이 흰색으로 메워지고 획은 굵어집니다. 이어서 침식하면 획만 원래 굵기로 돌아오고, 한 번 메워진 틈은 다시 열리지 않습니다. 여기서 바지의 구멍이 검은 구멍과 틈, 넓게 붙인 테이프가 팽창, 가장자리를 다듬는 가위질이 침식입니다.
왼쪽은 MORPH 글자의 획 다섯 군데에 굵기 2 칸의 틈을 내고, 획 안쪽에 반지름 2 칸의 검은 구멍 14개를 뚫은 그림입니다. 가운데의 팽창 뒤에는 틈과 구멍이 메워졌지만 글자가 뚱뚱해졌습니다. 오른쪽의 침식 뒤에는 글자가 원래 굵기로 돌아왔고 틈과 구멍은 메워진 채입니다.
닫기로 손계산하기
7×11 그림에 가운데가 빈 3×3 네모와, 한 칸 틈을 두고 떨어진 3×3 네모를 두고 3×3 도장으로 닫기 합니다.
| 단계 | 흰 칸 | 흰 덩어리 | 일어난 일 |
|---|---|---|---|
| 원본 | 17 | 2 | 왼쪽 네모 가운데에 구멍 한 칸, 두 네모 사이에 틈 한 줄 |
| 팽창 뒤 | 45 | 1 | 구멍과 틈이 메워지고 둘레로 한 겹 커진다 |
| 침식 뒤(닫기) | 21 | 1 | 둘레만 깎여 3×7 네모 하나가 된다 |
짧은 예시
import cv2
import numpy as np
img = np.zeros((7, 11), np.uint8)
img[2:5, 2:5] = 255 # 왼쪽 3×3 네모
img[3, 3] = 0 # 그 가운데의 구멍 한 칸
img[2:5, 6:9] = 255 # 한 칸 틈을 두고 떨어진 오른쪽 3×3 네모
se = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# MORPH_CLOSE = 닫기(팽창한 뒤 침식)
closed = cv2.morphologyEx(img, cv2.MORPH_CLOSE, se)
print((closed // 255).tolist())
print("흰 칸:", int((img == 255).sum()), "→", int((closed == 255).sum()))
print("흰 덩어리:", cv2.connectedComponents(img)[0] - 1, "→", cv2.connectedComponents(closed)[0] - 1)
# 결과: 흰 칸 17 → 21, 흰 덩어리 2 → 1손계산 표의 팽창 뒤 흰 칸 45개는 cv2.dilate(img, se) 로 따로 세어 본 값입니다. 바깥 둘레에 두 칸씩 여유를 둔 까닭은, 팽창한 덩어리가 그림 가장자리에 닿으면 침식 절의 주의할 점처럼 가장자리 쪽이 깎이지 않아 결과가 달라지기 때문입니다.
주의할 점
- 닫기는 도장보다 작은 검은 것을 모두 메웁니다. 글자 O, P, R 의 안쪽 구멍이나 와셔의 가운데 구멍처럼 지켜야 할 구멍이 있으면 도장을 그보다 작게 고릅니다.
- 닫기는 가까이 있는 두 물체를 하나로 이을 수도 있습니다. 물체 사이 틈이 도장보다 좁으면 붙어 버립니다.