모폴로지 연산은 영상 내부 객체의 형태아 구조를 분석하고 처리하는 기법이다. 주로 이진화된 영상에서 객체의 모양을 변형하는 용도로 사용된다. 객체모양 단순화, 잡음 제거
먼저 구조 요소를 정의해야한다. 대부분의 모폴로지 연산에서는 3x3 정방형 구조 요소를 사용하며 구조요소의 중심을 고정점으로 사용한다.
영상의 모폴로지 기법 중에서 가장 기본이 되는 연산은 침식과 팽창이다. 이진영상의 침식 연산은 객체 영역의 외곽을 골고루 깎아내는 연산으로 전체적으로 객체 영역은 축소되고 배경은 확대된다. 구조요소를 영상 전체에 대해 스캔하면서, 구조 요소가 객체 영역 내부에 완전히 포함될 경우 고정점 위치 픽셀을 255로 설정한다.
팽창연산은 객체 외곽을 확대하는 연산이다. 팽창연산을 수행하면 객체 영역은 확대되고 배경영역은 줄어든다. 팽창 연산은 구조요소를 영상 전체에 대해 이동시키면서, 구조 요소와 객체 영역이 한 픽셀이라도 만날 경우 고정점 위치 픽셀을 255로 설정한다.
OpenCV 에서는 널리 사용되는 모양의 구조 요소 행렬을 간단하게 생성할 수 있도록 getStructuringElement()함수를 제공한다.
Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1, -1));
shape : 구조 요소의 모양
ksize : 구조 요소의 크기
anchor : MORPH_CROSS 모양의 구조 요소에서 십자가 중심좌표
반환값 : 구조 요소 행렬
침식연산
void erode(InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefalutBorderValue());
src : 입력 영상
dst : 출력 영상
kernel : 구조 요소
anchor : 고정점 위치
iterations : 반복 횟수
borderType : 가장자리 픽셀 확장 방식
borderValue : borderType이 BORDER_CONSTANT인 경우, 확장된 가장자리 픽셀을 채울 값
팽창연산
void dilate(InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue());
src : 입력 영상
dst : 출력 영상
kernel : 구조 요소
anchor : 고정점 위치
iterations : 반복 횟수
borderType : 가장자리 픽셀 확장 방식
borderValue : borderType이 BORDER_CONSTANT인 경우, 확장된 가장자리 픽셀을 채울 값
void erode_dilate() {
Mat src = imread("milkdrop.bmp", IMREAD_GRAYSCALE);
if (src.empty()) {
cerr << "Image load failed!" << endl;
return;
}
Mat bin;
threshold(src, bin, 0, 255, THRESH_BINARY | THRESH_OTSU);
Mat dst1, dst2;
erode(bin, dst1, Mat());
dilate(bin, dst2, Mat());
imshow("src", src);
imshow("bin", bin);
imshow("dst1", dst1);
imshow("dst2", dst2);
waitKey();
destroyAllWindows();
}
dst1 : 침식연산
dst2 : 팽창연산
열기와 닫기 연산은 침식과 팽창 연산을 이용하여 구현할 수 있다. 열기 연산은 입력 영상에 대해 침식 연산을 수행한 후, 다시 팽창 연산을 수행하는 연산이다.
닫기 연산은 팽창연산을 먼저 수행한 후, 다시 침식 연산을 수행하는 연산이다.
열기와 닫기 연산은 각각 침식과 팽창 연산이 한번씩 적용되기 때문에 객체 영역의 크기가 크게 바뀌지 않는다.
b : 열기
c : 닫기
void morphologyEx(InputArray src, OutputArray dst,
int op, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue());
src : 입력 영상
dst : 출력 영상
op : 모폴로지 연산 타입
kernel : 구조 요소
anchor : 고정점 위치
iterations : 반복 횟수
borderType : 가장자리 픽셀 확장 방식
borderValue : borderType 이 BORDER_CONSTANT인 경우, 가장자리 픽셀값