9장. Morphology: 침식, 팽창, 열기, 닫기
구조 요소
은행 창구의 도장을 떠올려 봅시다. 도장에는 정해진 모양이 새겨져 있어서, 종이 어디에 찍든 같은 모양이 찍힙니다. 모폴로지도 작은 도장을 그림 위의 모든 칸에 한 번씩 대 봅니다. 도장의 모양을 정한 작은 0/1 표가 구조 요소입니다. 1 인 자리만 도장에 새겨진 부분이고, 0 인 자리는 보지 않습니다.
흰 칸이 1(도장에 새겨진 자리), 검은 칸이 0 입니다. 왼쪽 네모(RECT)는 25칸이 모두 1, 가운데 십자(CROSS)는 가운데 줄 두 개의 9칸, 오른쪽 타원(ELLIPSE)은 네 귀퉁이를 뺀 17칸이 1 입니다. 여기서 도장의 모양이 구조 요소이고, 도장을 찍는 자리마다 가운데 칸이 "지금 정할 칸"입니다.
왼쪽 초록 상자는 6장에서 본 커널, 오른쪽 다홍 상자는 이 장의 구조 요소입니다. 둘 다 이웃 칸에 작은 표를 겹치고 한 칸씩 옮긴다는 점은 같습니다. 다른 점은 계산입니다. 커널은 칸마다 무게를 곱해 더하지만, 구조 요소는 곱하지 않고 "1 자리가 모두 흰가"(침식) 또는 "1 자리에 하나라도 흰 칸이 있나"(팽창)만 봅니다.
세 가지 모양
| 모양 | 상수 | 5×5 에서 1 인 칸 | 잘 맞는 곳 |
|---|---|---|---|
| 네모 | cv2.MORPH_RECT | 25 | 네모난 물체, 글자. 가장 흔히 쓴다 |
| 십자 | cv2.MORPH_CROSS | 9 | 가로·세로 방향만 조금씩 손질할 때 |
| 타원 | cv2.MORPH_ELLIPSE | 17 | 동전, 세포처럼 둥근 물체. 모서리가 둥글게 다듬어진다 |
짧은 예시
import cv2
# getStructuringElement = get structuring element(구조 요소 얻기)
se = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, # 모양: 타원
(7, 7)) # 크기: (가로, 세로)
print(se)
print("자료형:", se.dtype, "/ 1 인 칸:", int(se.sum()))
# 결과: 귀퉁이가 0 인 7×7 표, 자료형 uint8, 1 인 칸 33se.sum() 은 표 안의 숫자를 모두 더합니다. 1 과 0 뿐이므로 1 인 칸의 개수가 됩니다. 구조 요소를 직접 np.ones((5, 5), np.uint8) 로 만들어도 네모 도장과 같습니다.
주의할 점
- 크기는 3, 5, 7 처럼 홀수로 줍니다. 짝수도 오류는 나지 않지만 가운데 칸이 한쪽으로 치우쳐 결과가 반 칸 밀립니다.
- 크기는
(가로, 세로)순서입니다.(9, 1)처럼 주면 가로로 긴 막대 도장이 되어, 가로 방향 틈만 메우는 데 쓸 수 있습니다.