메뉴 닫기

OpenCV 외곽선(Contour) 검출

이진 영상에서 객체의 외곽선을 추출하는 방법에 대해 소개하도록 하겠습니다.

이진 영상에서 외곽선 검출하기

객체의 외곽선을 검출하는 함수 이름은 findContours 입니다. Contour 글자에 s가 붙은 것을 확인할 수 있습니다. 영상 내부에는 여러 개의 객체가 존재할 수 있고, 각 객체마다 독립된 외곽선으로 표현할 수 있습니다. 즉, findContours 함수는 영상 내에 존재하는 여러 객체의 외곽선을 검출하여 반환합니다.

하나의 외곽선은 점의 집합으로 구성됩니다. 그러므로 객체를 검출한 결과는 최종적으로 std::vector<std::vector<cv::Point>>으로 반환됩니다.

외곽선 검출 함수

void findContours(InputArray image, OutputArrayOfArrays contours, OutputArray hierarchy,

int mode, int method, Point offset = Point())

  • InputArray image: 입력영상 (8UC1)
  • OutputArrayOfArrays: 검출된 객체의 외곽선들 (e.g. std::vector<std::vector<cv::Point>>)
  • OutputArray hierarchy: 외곽선의 계층 정보를 받아옵니다. std::vector<cv::Vec4i>타입이며, 외곽선 개수만큼의 요소를 갖고 있습니다.
    ※ Vec4i 저장된 정보: hierarchy[i][0]: next, hierarchy[i][1]: prev, hierarchy[i][2]: first child, hierarchy[i][3]: parents
    ※ findContours 함수는 2개로 오버로딩 되어있는데, 차이는 hierarchy 인자의 유무임
  • int mode: 외곽선 검출 모드 설정
  • int method: 외곽선 근사화 알고리즘 설정

외곽선 검출모드

Enum Description
RETR_EXTERNAL 객체 최외곽선만 검출 (계층구조 X)
RETR_LIST 계층적 관계를 설정하지 않고 모든 외곽선을 검출
RETR_CCOMP 모든 외곽선을 검색하여 2단계 계층구조로 구성
RETR_TREE 모든 외곽선을 검색하고 전체 계층 구조를 구성

외곽선 근사화 알고리즘 설정

Enum Description
CHAIN_APPROX_NONE 모든 외곽선 점의 좌표를 저장
CHAIN_APPROX_SIMPLE 외곽선에서 수평, 수직 및 대각선 성분은 끝점만 저장
(직사각형 윤곽은 4개의 점으로 인코딩됨)
CHAIN_APPROX_TC89_L1 Teh-Chin L1 근사화 적용
CHAIN_APPROX_TC89_KCOS Teh-Chin k cos 근사화 적용

외곽선 검출 예제

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

using namespace std;
using namespace cv;

int main()
{
	Mat img = imread("contour.bmp", IMREAD_GRAYSCALE);

	if (img.empty()) {
		cerr << "failed to read image" << endl;
		return 1;
	}

	vector<vector<Point>> contours;
	//findContours(img, contours, RETR_LIST, CHAIN_APPROX_NONE);
	findContours(img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);

	Mat dst;
	cvtColor(img, dst, COLOR_GRAY2BGR);

	Scalar c(0, 0, 255);
	
	for (int i = 0; i < contours.size(); i++) {
		drawContours(dst, contours, i, c, 3);
	}

	imshow("img", img);
	imshow("dst", dst);

	waitKey(0);
	destroyAllWindows();

	return 0;
}

예제 결과



findContours(img, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE)



findContours(img, contours, hierarchy, RETR_LIST, CHAIN_APPROX_NONE)

위 예제에서는 RETR_LIST를 사용하든, RETR_TREE를 사용하든 보여지는 결과는 같습니다.

다만 RETR_LIST의 경우 hierarchy는 동등하기 때문에 vec4i는 0번(next)과 1번(prev) 요소만 사용하게 됩니다. RETR_TREE는 hierarchy가 설정되어 있기 때문에, 2번(first child)과 3번(parent)요소만 사용합니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다