9장. Morphology: 침식, 팽창, 열기, 닫기
모폴로지란
도화지에 찍힌 얼룩을 지우개로 지우는 장면을 떠올려 봅시다. 크게 칠한 그림은 그대로 두고, 그 둘레에 튄 작은 점만 지웁니다. 반대로 칠하다 빠뜨린 작은 틈은 크레파스로 살짝 덧칠해 메웁니다. 모폴로지는 이진 그림에서 이 두 가지 손질을 칸 단위로 하는 일입니다. 흰 덩어리를 물체로 보고, 그 모양을 깎거나 덧붙여 고칩니다.
그림을 왼쪽부터 읽습니다. 8장에서 흑백 사진을 이진화하면 이진 그림이 나오지만, 그 안에는 잡티, 구멍, 끊김이 남습니다. 모폴로지로 흰 덩어리의 모양을 고친 뒤에야 "물체가 몇 개인가", "넓이가 얼마인가"를 바로 잴 수 있습니다. 여기서 도화지의 그림이 흰 덩어리이고, 지우개질과 덧칠이 모폴로지의 두 동작입니다.
왼쪽은 흰 글자 MORPH 에 일부러 흰 잡티를 뿌리고, 획에 가는 틈과 작은 검은 구멍을 낸 가상의 그림입니다. 가운데는 이 장에서 배울 닫기와 열기를 5×5 도장으로 차례로 건 결과입니다. 잡티가 거의 사라지고 틈과 구멍이 메워져 오른쪽의 본래 글자에 가까워졌습니다. M 아래의 작은 흰 점과 위쪽 가장자리의 아주 작은 점 둘은 남았는데, 그 까닭은 "순서가 왜 중요한가" 절에서 봅니다.
이진화 뒤에 흔히 남는 것
| 남는 것 | 생기는 까닭 | 생기는 일 | 고치는 연산 |
|---|---|---|---|
| 흰 잡티 | 바탕의 먼지, 노이즈가 임계값을 넘음 | 물체 수가 많게 세어진다 | 열기 |
| 검은 구멍 | 물체 위의 반사광, 밝은 무늬 | 넓이가 작게 재어진다 | 닫기 |
| 끊긴 획 | 가늘거나 흐린 곳이 임계값을 못 넘음 | 글자 하나가 여러 조각으로 세어진다 | 닫기 |
| 붙은 덩어리 | 가까운 두 물체 사이가 어두움 | 두 개가 하나로 세어진다 | 열기, 침식 |
짧은 예시
import cv2
import numpy as np
# 끊긴 글자와 본래 글자를 흑백으로 읽는다
clean = cv2.imread("ch09_letters_clean.png", cv2.IMREAD_GRAYSCALE)
broken = cv2.imread("ch09_letters_broken.png", cv2.IMREAD_GRAYSCALE)
print("들어 있는 값:", [int(v) for v in np.unique(broken)]) # 결과: [0, 255] → 이진 그림
print("흰 칸 수:", int((clean == 255).sum()), int((broken == 255).sum()))
# 두 그림에서 값이 다른 칸의 수
print("다른 칸:", int((clean != broken).sum()))교안 PC 에서는 흰 칸이 본래 글자 6375개, 끊긴 글자 5863개이고, 다른 칸은 512개입니다. 틈과 구멍 자리의 흰 칸이 검게 바뀐 만큼 줄었습니다.
주의할 점
- 이 장의 연산은 흰 칸을 물체로 봅니다. 어두운 글자나 부품이 검은색인 그림은 8장의
THRESH_BINARY_INV로 물체를 흰색으로 만든 뒤에 씁니다. - 모폴로지는 흑백(0~255) 그림에도 쓸 수 있습니다. 이 장에서는 결과를 읽기 쉬운 이진 그림만 다룹니다.