모폴로지

  • 모폴리지 연산
    • 영상을 형태학적인 측면에서 다루는 기법
      • 이진 영상에서 흰색으로 되어있는 객체의 모양 및 각각의 객체가 이어져 있는지 안 이어져 있는지 등의 관점에서 다룸
    • 다양한 영상 처리 시스템에서 전처리(pre-processing) 또는 후처리(post-processing) 형태로 널리 사용
    • 수학적 모폴로지(mathematical morphology)
  • 구조 요소(structureing element)
    • 모폴로지 연산의 결과를 결정하는 커널, 마스크
    • 3 x 3 크기의 정방행렬을 가장 많이 사용함

image

침식과 팽창

침식
  • 이진 영상의 침식(erosion) 연산
    • 구조 요소가 객체 영역 내부에 완전히 포함될 경우 고정점 픽셀을 255로 설정
    • 침식 연산은 객체 외곽을 깎아 내는 연산으로 객체의 크기는 줄어들고 배경은 확대됨

image

  • 실제 영상의 침식 연산 결과
    • 차례대로 원본 영상, 침식 1번, 침식 2번, 침식 3번 수행
    • 객체 영역(흰색)이 점점 줄어들면서 깎여 나가고, 객체 내부의 검정색 부분인 홀(hole)이 점점 커짐
    • 객체 밖의 작은 크기들의 잡음이 점점 제거됨

image

모폴로지 침식 연산 함수
void erod(InputArray src, OutputArray dst, InputArray kernel, Point anchor = Point(-1,-1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue());
  • src : 입력 영상
  • dst : 출력 영상(src와 동일한 크기와 타입)
  • kernel : 구조 요소
    • Mat()을 지정하면 3 x 3 사각형 구성 요소를 사용
    • getStructuringElement() 함수에 의해 생성 가능
  • anchor : 고정점 위치. Point(-1, -1)이면 중앙점을 사용
  • iterations : 반복 횟수
구조 요소(커널) 생성
Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));
  • shape : 구조 요소 모양 지정 상수
    • MORPH_RECT : 사각형 모양
    • MORPH_CROSS : 십자가 모양
    • MORPH_ELLIPSE : 사각형에 내접하는 타원
  • ksize : 구조 요소 크기
  • anchor : MORPH_CROSS 모양의 구조 요소에서 중심 좌표로 Point(-1, -1)을 지정하면 구조 요소의 중앙점을 사용
  • 반환값 : 0과 1로 구성된 CV_8UC1 타입의 행렬

#####

팽창
  • 이진 영상의 팽창(dilation) 연산
    • 구조 요소와 객체 영역이 한 픽셀이라도 만날 경우 고정점 픽셀을 255로 설정
    • 팽창 연산은 객체 외곽을 확대시키는 연산

image

  • 실제 영상의 팽창 연산 결과
    • 차례대로 원본 영상, 팽창 1번, 팽창 2번, 팽창 3번 수행
    • 객체 영역(흰색)이 점점 불어나고, 객체 내부의 홀이 채워짐
    • 객체 밖의 작은 크기들의 잡음도 점점 커짐

image

모폴로지 팽창 연산 함수
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 : 출력 영상(src와 동일한 크기와 타입)
  • kernel : 구조 요소
    • Mat()을 지정하면 3 x 3 사각형 구성 요소를 사용
    • getStructuringElement() 함수에 의해 생성 가능
  • anchor : 고정점 위치. Point(-1, -1)이면 중앙점을 사용
  • iterations : 반복 횟수

열기와 닫기

열기(opening) 연산
  • 열기 : 침식 -> 팽창
닫기(closing) 연산
  • 닫기 : 팽창 -> 침식

  • 열기와 닫기 연산 효과

    • 열기 : 각각의 객체가 미세하게 연결되어있는 것을 끊어주고 작은 픽셀들의 잡음을 제거
    • 닫기 : 객체 안의 홀들이 사라지고, 객체 바깥의 작은 크기들은 유지

image

범용 모폴로지 연산 함수

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 : 모폴로지 연산 상수
    • MORPH_ERODE : 침식
    • MORPH_DILATE : 팽창
    • MORPH_OPEN : 열기
    • MORPH_CLOSE : 닫기
    • MORPH_GRADIENT : 모폴로지 그래디언트 = 팽창 - 침식
  • kernel : 구조 요소
  • anchor : 고정점
  • iterations : 반복 횟수

열기 연산을 이용한 잡음 제거 예제

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main(void)
{
	Mat src = imread("rice.png", IMREAD_GRAYSCALE);

	if (src.empty()) {
		cerr << "Image load failed!" << endl;
		return -1;
	}

	// 지역 이진화
	Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC1);
	int bw = src.cols / 4;
	int bh = src.rows / 4;

	for (int y = 0; y < 4; y++) {
		for (int x = 0; x < 4; x++) {
			Mat src_ = src(Rect(x*bw, y*bh, bw, bh));
			Mat dst_ = dst(Rect(x*bw, y*bh, bw, bh));
			threshold(src_, dst_, 0, 255, THRESH_BINARY | THRESH_OTSU);
		}
	}

	// 레이블링 함수를 이용한 흰색 객체 갯수 구하기
	Mat labels;
	
	int cnt1 = connectedComponents(dst, labels); // dst의 흰색 객체의 개수에 1을 더한 값을 반환함
	cout << "# of objects in dst: " << cnt1 - 1 << endl;

	Mat dst2;
	morphologyEx(dst, dst2, MORPH_OPEN, Mat()); 
	// 지역 이진화 결과인 dst에 대해서 모폴리지 연산의 열기 연산을 수행하고 그 결과를 dst2에 저장
	// erode(dst, dst2, Mat());
	// dilate(dst2, dst2, Mat()); // 다음 2줄을 morphologyEx 로 대체해도 같은 결과가 나옴
	
	int cnt2 = connectedComponents(dst2, labels); // dst2의 흰색 객체의 개수에 1을 더한 값을 반환함
	cout << "# of objects in dst2: " << cnt2 - 1 << endl;

	imshow("src", src);
	imshow("dst", dst);
	imshow("dst2", dst2);
	waitKey();
}

image

  • dst2 결과는 dst 결과의 작은 픽셀들의 잡음을 제거

image

  • dst의 객체 개수는 112개, dst2의 객체 개수는 98개로 검출됨

image