모폴로지 연산
구조화 요소를 이용한 침식·팽창·열림·닫힘
image = cv.imread("shapes.webp")
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
_, binary = cv.threshold(
gray,
60, # 임계값
255, # 임계값보다 밝은 픽셀에 넣을 값
cv.THRESH_BINARY,
)
to_pil(binary)
임계값 60보다 밝은 픽셀은 흰색 처리. 흰색 영역에는 도형 17개와 배경의 작은 밝은 점이 남는다.

구조화 요소
모폴로지 연산(morphological operation)은 구조화 요소(structuring element)를 주변 픽셀에 적용하여 이진 객체의 형태를 바꾸는 처리. OpenCV에서는 0이 아닌 픽셀을 흰색 전경으로 취급.
kernel = cv.getStructuringElement(
cv.MORPH_ELLIPSE, # 모양. MORPH_RECT, MORPH_CROSS도 사용 가능
(3, 3), # 크기
)
kernel
array([[0, 1, 0],
[1, 1, 1],
[0, 1, 0]], dtype=uint8)
커널에서 값이 1인 중심과 상하좌우 5개 픽셀이 연산에 참여. 커널이 클수록 한 번의 연산 범위도 확대.
침식과 팽창
침식(erosion)은 커널 영역의 최솟값을 사용. 위의 십자형 커널에서는 5개 픽셀 중 하나라도 검은색(0)이면 결과도 검은색(0). 따라서 흰색 전경 축소.
E(x,y)=(i,j)∈KminB(x+i,y+j)- 객체의 바깥 경계가 안쪽으로 이동
- 작은 흰색 점과 가는 돌출부 제거
- 가는 연결 부분의 단절 가능
팽창(dilation)은 커널 영역의 최댓값을 사용. 위의 십자형 커널에서는 5개 픽셀 중 하나라도 흰색(1)이면 결과도 흰색(1). 따라서 흰색 전경 확대.
D(x,y)=(i,j)∈KmaxB(x+i,y+j)- 객체의 바깥 경계가 바깥쪽으로 이동
- 작은 검은색 구멍과 끊어진 간격 축소
- 가까운 객체의 결합 가능
eroded = cv.erode(binary, kernel)
dilated = cv.dilate(binary, kernel)
to_pil(cv.hconcat([eroded, dilated]))

침식으로 도형과 흰색 잡음이 함께 축소. 팽창으로 도형이 굵어지고 작은 흰색 잡음도 확대.
열림과 닫힘
열림(opening)은 침식 후 팽창. 큰 객체의 크기를 대체로 복원하면서 커널보다 작은 흰색 잡음을 제거.
B∘K=(B⊖K)⊕K닫힘(closing)은 팽창 후 침식. 객체의 크기를 대체로 복원하면서 작은 검은색 구멍과 끊긴 부분을 메우는 연산.
B∙K=(B⊕K)⊖Kopened = cv.morphologyEx(
binary,
cv.MORPH_OPEN,
kernel,
)
cleaned = cv.morphologyEx(
opened,
cv.MORPH_CLOSE,
kernel,
)
to_pil(cv.hconcat([opened, cleaned]))
각 단계의 검출 객체 수 비교. cv.findContours()는 이진 이미지에서 객체의 경계를 찾는 함수.
raw_contours, _ = cv.findContours(
binary,
cv.RETR_EXTERNAL,
cv.CHAIN_APPROX_SIMPLE,
)
opened_contours, _ = cv.findContours(
opened,
cv.RETR_EXTERNAL,
cv.CHAIN_APPROX_SIMPLE,
)
cleaned_contours, _ = cv.findContours(
cleaned,
cv.RETR_EXTERNAL,
cv.CHAIN_APPROX_SIMPLE,
)
len(raw_contours) # before
176
len(opened_contours) # after opening
17
len(cleaned_contours) # after closing
17

이진화 직후에는 배경의 작은 밝은 점까지 객체로 잡혀 176개 검출. 열림 후 실제 도형 수인 17개로 감소. 닫힘은 도형 내부의 작은 틈을 정리하면서 17개 객체를 유지.
퀴즈
흰색을 전경으로 보는 이진 이미지의 침식과 팽창에 대한 설명으로 맞는 것을 모두 고르세요.
퀴즈를 풀려면 대화형 기능을 불러와야 합니다.