Watershed 알고리즘을 사용하여 영상 분할(Image segmentation) 하는 방법에 대해 설명합니다.
다음 OpenCV Python 튜토리얼을 참고하여 강좌를 비정기적로 포스팅하고 있습니다. https://docs.opencv.org/4.0.1/d6/d00/tutorial_py_root.html |
그레이스케일 이미지에서 높은 픽셀값을 가지는 부분을 언덕으로 보고, 낮은 픽셀값을 가지는 부분을 계곡으로 볼 수 있습니다.
한 이미지에 여러 개의 고립된 계곡(극소점)이 있을 수 있습니다. 각각 다른 색의 물(라벨)로 물을 채운다고 합시다.
수위가 상승함에 따라 다른색의 물로 채워지던 계곡들이 하나로 합쳐질 수 있습니다. 이것을 방지하기 위해 물이 합류되는 지점에 벽을 쌓습니다.
모든 언덕이 물에 잠길때까지 물을 채우고 벽을 쌓는 것을 반복합니다. 그런 다음 생성한 벽을 사용하여 영상 분할을 할 수 있습니다.
아래 그림처럼 수위(h)가 높아짐에 따라 다른 계곡과의 경계점에 벽(수직선)을 추가하게 됩니다.
이미지 출처 - https://imagej.net/Classic_Watershed
하지만 이런 접근은 노이즈 등으로 인해 영상 분할이 필요 이상으로 될 수 있습니다.
그래서 OpenCV에서는 마커 기반 watershed 알고리즘을 구현합니다. 병합될 계곡점과 그렇지 않을 계곡점을 지정해주는 방법입니다.
watershed 알고리즘을 적용하기 전에 영역을 나누어 라벨을 부여해줍니다. 오브젝트라고 생각되는 영역과 배경이라고 생각되는 영역에 라벨을 부여합니다. 아직 배경인지 오브젝트인지 확실치 않은 영역은 라벨로 0을 부여합니다. 이런 식으로 이미지에 라벨을 부여하는 것을 마커라고 합니다.
이제 watershed 알고리즘을 적용합니다. 마커 지점부터 시작하여 라벨값을 주변으로 확장하며 라벨값이 0인 영역에 대한 라벨값을 업데이트합니다. 오브젝트간 경계의 라벨은 -1이 됩니다.
아래 이미지에서 동전이 서로 붙어있습니다. watershed 알고리즘과 Distance Transform을 사용하여 서로 붙어있는 동전을 분리해보겠습니다.
이진화를 적용하여 배경과 동전을 분리합니다.
import numpy as np |
동전들이 붙어있는 상태로 검출됩니다.
오프닝을 적용하여 노이즈를 제거하고 팽창(dilate)연산을 적용하여 동전 영역내에 있을수 있는 공백을 메웁니다.
kernel = np.ones((3,3),np.uint8) sure_bg = cv.dilate(opening,kernel,iterations=3) |
동전이 검출될 수 있는 배경 영역(sure_bg)입니다.
동전 중앙 부분을 검출하기 위해서 distance transform를 적용한 후 이진화를 합니다. 오른쪽 이미지가 동전 영역이 확실한 동전 중앙 영역(sure_fg)입니다.
dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 5) |
Distance Transform 결과 이진화 적용 후 결과
배경 영역(sure_bg)에서 동전 중앙 영역(sure_fg)을 뺍니다.
sure_fg = np.uint8(sure_fg) |
아래 이미지처럼 동전인지 배경인지 아직 알 수 없는 영역(unknown)이 존재하게 됩니다.
동전 중앙 영역 이미지를 라벨링한 후, 아직 동전인지 배경인지 알 수 없는 영역의 라벨값을 0으로 지정합니다. 배경이 확실한 영역의 값은 1이됩니다.
# Marker labelling |
watershed 알고리즘을 적용하면 동전 외곽은 라벨값으로 -1을 가지며 배경은 라벨값으로 1을 갖게됩니다.
markers = cv.watershed(img, markers) |
실행 결과입니다. 동전의 접촉면이 분리되었지만 정확하지는 않습니다.
테스트에 사용한 전체 코드입니다.
import numpy as np |
최초 작성 2019. 1. 8
'OpenCV > OpenCV 강좌' 카테고리의 다른 글
OpenCV의 SURF 동영상 매칭 테스트 (70) | 2019.01.23 |
---|---|
OpenCL 사용 여부에 따른 OpenCV 성능 비교 테스트 (5) | 2019.01.22 |
OpenCV Python 강좌 - Distance Transform (0) | 2019.01.08 |
OpenCV Python 강좌 - 템플릿 매칭(Template Matching) (2) | 2019.01.03 |
OpenCV Python 강좌 - 8. Hough Line Transform (15) | 2018.12.24 |
시간날때마다 틈틈이 이것저것 해보며 블로그에 글을 남깁니다.
블로그의 문서는 종종 최신 버전으로 업데이트됩니다.
여유 시간이 날때 진행하는 거라 언제 진행될지는 알 수 없습니다.
영화,책, 생각등을 올리는 블로그도 운영하고 있습니다.
https://freewriting2024.tistory.com
제가 쓴 책도 한번 검토해보세요 ^^
그렇게 천천히 걸으면서도 그렇게 빨리 앞으로 나갈 수 있다는 건.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!