모폴로지: 영상 처리시스템에서 전처리(pre proceessing) 또는 이진화 수행후 후처리(post processing) 에서 널리사용

구조요소 (structuring element) : 모폴로지 연산 결과를 결정하는 커널 , 마스크. 

1x3 , 3x1   , 3x3, 5x5, 십자형태 등 다양한 형태 마스크 가짐. 

 

 1. 침식(erosion)과 팽창(dilation)

침식 erode: 흰색 객체 외곽 부분 깎아냄.

(구조요소가 이동할 때마다 객체 부분과 만나면 이 만나는 것을 무시하지 않코, 구조요소가 객체 안에 완전히 들어가 있을 때 가운데 픽셀을 마킹 한다. 이 과정을 영상 전체를 스캐닝함으로써 마킹한 픽셀들 이외의 픽셀들을 깎아낸다. 

객체 영역이 점점 줄어들고, 객체 내부의 홀은 커지며 작은 크기의 잡음을 제거하는 효과를 가진다.

void erode(InputArray src, OutputArray dst, InputArray kernel, Point anchor = Point(-1, -1),
int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue());

dst: src와 동일 크기와  타입

kernel : 구조요소, Mat() 를 지정하면 3x3 사각형 구성요소 사용.  getSturcturingElement() 함수에 의해 생성 가능.

anchor: 고정점 위치. Point(-1, -1) 이면 중앙점 사용

iterations: 반복횟수.   , 침식연산 n번 수행하고자 할 경우 iterations =  n 번 입력하면됨

 

 

팽창(dilation) : 구조요소를 전체 영상 스캐닝하다, 객체 영역을 한 픽셀이라도 만날 경우 고정점 픽셀(가운데 픽셀)을 255로 설정(마킹)

객체 영역(흰색)이 점점 불어나고, 객체 내부의 홀이 채워짐. 바깥 노이즈가 커지는 현상이 있다. 

void dilate(InputArray src, OutputArray dst, InputArray kernel, Point anchor = Point(-1,-1),
int iterations = 1, int borderType = BORDER_CONSTANT, 
const Scalar& borderValue = morphologyDefaultBorderValue());

dst: src와 동일 크기와 타입.

kernel: 구조요소. Mat()를 지정하면 3x3사각형 구성요소 사용.

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 타입의 행렬( 1의 위치가 구조요소모양 결정)

 

 

2. 열기와 닫기

열기 = 침식 -> 팽창

Opening = Erosion -> Dilation

 

닫기 = 팽창 -> 침식

Closing = Dilation -> Erosion

 

 

3. 범용 모폴로지 연산함수

 

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());

op: 모폴로지 연산 상수

MORPH_ERODE 침식
MORPH_DDILATE 팽창
MORPH_OPEN 열기
MORPH_CLOSE 닫기
MORPH_GRADIENT 모폴로지 그래디언트 = 팽창 - 침식

kernel: 구조요소

anchor: 고정점

iterations: 반복횟수

 

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

using namespace std;
using namespace cv;

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

	if (src.empty()) {
		cerr << "Image laod 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;
	
	//dst는 지역이진화기법을 통해 구한 이진화영상이며 이를 input 영상으로 설정
	int cnt1 = connectedComponents(dst, labels); // 흰색 객체 갯수 세주는 함수로 흰색 객체갯수 +1 을 반환

	//connectedComponents 레이블링과 외곽선 검출에서 다룰 예정
	cout << "# of objects in dst: " << cnt1 - 1 << endl;  // 객체갯수 +1 의 1을 제거하고자 -1.

	Mat dst2;
	//dst를 모폴로지 열기 를 적용해 dst2 에 저장.
	//morphologyEx(dst, dst2, MORPH_OPEN, Mat());
	erode(dst, dst2, Mat());
	dilate(dst2, dst2, Mat());
	int cnt2 = connectedComponents(dst2, labels);
	cout << "# of object in dst2: " << cnt2 - 1 << endl;

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

'프로그래머스 > OPENCV' 카테고리의 다른 글

OpenCV 외곽선 함수와 응용  (1) 2022.12.09
레이블링과 외곽선 검출  (0) 2022.12.08
지역이진화  (0) 2022.12.08
컬러영상 처리 기초 (이진화 게시글과 swap됨 )  (0) 2022.12.08
코너 검출 기법  (2) 2022.12.08

+ Recent posts