본문 바로가기

[ 프로그래밍 ]/강좌

OpenCV 강좌 08. 마커 추출 (3) - 마커 꼭지점 구하기

마커의 영역이 추출되면 그 마커의 윤곽선만을 추출해 낼 수 있으며,
이를 위해 OpenCV에서는 cvFindContours() 함수를 제공하고 있다.

/* Retrieves outer and optionally inner boundaries of white (non-zero) connected
   components in the black (zero) background */

CVAPI(int)  cvFindContours( CvArr* image, CvMemStorage* storage, CvSeq** first_contour,
                            int header_size CV_DEFAULT(sizeof(CvContour)),
                            int mode CV_DEFAULT(CV_RETR_LIST),
                            int method CV_DEFAULT(CV_CHAIN_APPROX_SIMPLE),
                            CvPoint offset CV_DEFAULT(cvPoint(0,0)));
CvArr* image는 0을 배경으로 0이 아닌 값(백색)을 개체로 하는 영상이며,
CvSeq** first_contour에 윤곽선 정보가 들어간다.

이를 이용하여 윤곽선을 추출한 뒤, 이를 이용하여 마커의 네 꼭지점을 구한다.

1. 윤곽선 검출

CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contours   = 0;


마커의 이미지가 들어갈 영상을 생성한 뒤 윤곽선을 추출한다.
다섯 번째 인수인 윤곽 추출 모드는 CV_RETR_TREE로 지정한다. 이는 영상 내의 모든 윤곽을 추출해 분기된 윤곽 모두를 계층구조로 나타낸다. 여섯 번째 인수는 윤곽점 중 특징점(두 점을 잇는 직선으로 표현 안되는 점)들만 배열에 정렬하기 위해 CV_CHAIN_APPROX_SIMPLE로 둔다.
cvDrawContours()를 이용하면 영상 위에 간단하게 윤곽선을 출력할 수 있다.

2. 꼭지점 추출
- 임의의 점에서 가장 먼 점을 첫 번째 꼭지점으로 설정한다.


CvSeq* 형의 contours 변수에서 CvPoint* 형의 실제 좌표를 가져올 수 있다.
CvPoint *st  = (CvPoint *)cvGetSeqElem( contours, 0 );
시퀀스의 첫 점을 초기위치로 하여 모든 특징점들과의 거리를 계산한다.

첫 번째 점은 corner[0]에 저장한다.

- 같은 방법으로 두 번째 꼭지점을 구할 수 있다.
직사각형의 경우 당연히 대각점이 가장 먼 점이 되지만,
사각형은 경우에 따라 아래와 같이 여러 방향에서 두 번째 꼭지점이 나타난다.
두 번째 점은 corner[1]에 저장한다.

- 세 번째 꼭지점은 첫 번째, 두 번째 점에서 가장 먼 점을 구한다.
세 번째 점은 corner[2]에 저장한다.


- 이렇게 하면 어떻게든 세 개의 꼭지점을 구해낼 수 있다.
이제 네 번째 꼭지점이 눈앞이다.

- 그런데 문제가 있다.
같은 방법으로 네 번째 꼭지점을 구하는 일이 항상 가능한 일이 아니라는 점은 아래 테스트 영상에서 확인할 수 있다.


첫 번째 점은 좌측 하단의 점 (136,381)이고, 두 번째 점은 우측 하단의 점 (418,340)이다.
첫 번째, 두 번째 점에서 거리가 가장 먼 점은 좌측 상단의 점 (153,255)이다.
세 개의 점에서 가장 먼 점이 우측상단의 점이 되어야 하지만, 애석하게도 그 점은 우측 하단의 점 (481, 336)이다.

- 이런 이유로 거리정보만으로 네 꼭지점 모두를 구하는 것은 무리가 있다고 하겠다.
이 시점에서는 사각형의 넓이정보를 이용한다.

직교 좌표계에서 각 꼭지점의 좌표가 그 내부를 반시계방향으로 도는 순서대로 (x1,y1), (x2,y2), ... , (xn,yn)로 주어져 있는 단순한 다각형의 넓이 A는 다음과 같이 계산할 수 있다.


이 공식은 1769년 마이스터가, 1795년 가우스가 사용하였다.


- 알고리즘에서는 이미 구해둔 세 개의 꼭지점과 나머지 한 점. 즉, 윤곽선 상의 모든 점 (x, y)을 세 개의 삼각형으로 나눈 뒤 그 넓이의 합이 최대가 되는 점 (x, y)를 네 번째 꼭지점으로 정한다.


3. 추출된 꼭지점과 좌표 출력
- 글자는 안겹치게 5픽셀씩 오른쪽으로 밀어주는 센스! ^^*

4. 테스트
- 단일 마커


- 다중 마커





이제 강좌도 막바지에 접어듭니다.
다음편에는 여기에 뮤직비디오를 뿌립니다.
기대하세요!