차근차근/OpenCV

외곽선 검출하기

예쁜꽃이피었으면 2014. 8. 5. 17:00

http://lueseypid.tistory.com/80


■ 외곽선

외곽선이란 영상 내 곡선을 나타내는 점들의 리스트로 정의된다. OpenCV에서 곡선은 시퀀스를 이용하여 표현되고, 이때 시퀀스 내부에는 곡선에서 다음 점에 대한 위치 정보가 저장되어있다. 


■ 외곽선 검출 - cvFindContours()

 int cvFindContours(

      CvArr* image,

      CvMemStorage* storage,

      CvSeq** first_contour,

      int header_size=sizeof(CvContour),

      int mode=CV_RETR_LIST,

      int method=CV_CHAIN_APPROX_SIMPLE,

      CvPoint offset=cvPoint(0,0)

);

img : 입력영상으로 항상 8비트 단일 채널이여야 하며, 이진영상으로 취급된다.

storage : 검출된 외곽선의 기록을 위해 필요한 메모리 스토리지

first_contour : CvSeq*에 대한 포인터(이중포인터)로 함수 내부에서 first_coutour를 자체적으로 할당하기 때문에 외부에서 사용자가 직접 할당하면 안된다.

headsize : 어떤 객체를 할당할 것인지를 알려준다.

mode : 어떤종류의 외곽선을 찾을것인가 또는 어떻게 결과를 표현할 것인가를 알려주는 용도로 사용된다. 

mode값 내용 
 CV_RETR_EXTERNAL 가장 바깥쪽에 나타나는 외곽선들만 검출한다. 
 CV_RETR_LIST

 모든 외곽선을 검색하고 리스트에 넣는다. 

 CV_RETR_CCOMP

 모든 외곽선을 검색하고 이를 두개의 계층으로 나누어 관리한다. 
 (구성요소들의 바깥쪽 외곽선들을 연결 리스트로 관리하고, 두번째 계층에서는 구성 요소들의 안쪽 외곽선을 리스
  트로 관리한다.) 
 CV_RETR_TREE

 모든 외곽선들을 검색하여 외곽선들의 전체 계층구조를 생성한다. 


method : 외곽선을 어떻게 근사화 할것인지 알려준다

method값

 내용 

 CV_CHAIN_CODE

 프리만 체인코드를 생성한다. 

 CV_CHAIN_APPROX_NONE

 체인 코드의 모든 점을 꼭지점으로 변환한다. 
 CV_CHAIN_APPROX_SIMPLE 수평, 수직, 대각 성분의 끝점만 저장한다. 
 CV_CHAIN_APPROX_TC89_L1, 
 CV_CHAIN_APPROX_TC89_KCOS

 Teh-Chin의 체인 근사화 알고리즘 중 하나를 적용한다.

 CV_LINK_RUNS

 ??

cvFindContours()함수는 수행후 검출된 외곽선들의 전체 개수를 반환한다.

 

■ cvStartFindContours()

cvStartFindContours()함수는 한번에 하나의 외곽선만 찾기 원할 때 사용된다. 이 함수는 CvContourScanner를 반환하며, CvContourScanner는 어느 시퀀스가 이미 읽혀졌는지 또는 그렇지 않은지에 대한 정보를 가지고 있다. 

 CvContourScanner cvStartFindContours(

        CvArr* image,

        CvMemStorage* storage,

        int header_size=sizeof(CvContour),

        int mode=CV_RETR_LIST,

        int method=CV_CHAIN_APPROX_SIMPLE,

        CvPoint offset=cvPoint(0,0)

);


■ cvFindNextContour()

검출된 외곽선을 순차적으로 검색하며, 검색할 외곽선이 존재하지 않을경우 NULL을 반환한다.

 CvSeq* cvFindNextContour(CvContourScanner scanner);


■ cvSubstitueContour()

스캐너가 현재 가리키고 있는 외곽선을 다른 외곽선으로 대체할 때 사용된다.

 void cvSubstituteContour(CvContourScanner scanner, CvSeq* new_contour);


■ cvEndFindContour()

스캐닝이 끝난후 스캐너를 완료 상태로 설정한다.스캐너가 사용하였던 시퀀스를 삭제하지 않고, 시퀀스의 첫번째 원소에 대한 포인터를 반환한다.

 CvSeq* cvEndFindContours(CvContourScanner* scanner);


■ cvApproxChains()

프리만 체인을 정확하게 또는 근사화하여 다각형 표현방식으로 표현한다.

 CvSeq* cvApproxChains(

        CvSeq* src_seq,

        CvMemStorage* storage,

        int method=CV_CHAIN_APPROX_SIMPLE,

        double parameter=0,

        int minimal_perimeter=0,

        int recursive=0

);


■ 외곽선 그리기 - cvDrawContours()

 void cvDrawContours(

        CvArr *img,

        CvSeq* contour,

        CvScalar external_color,

        CvScalar hole_color,

        int max_level,

        int thickness=1,

        int line_type=8,

        CvPoint offset =cvPoint(0,0)

);

img : 외곽선이 그려질 입력영상

contours : 외곽선 트리의 루트 노드

external_color : 외부 외곽선의 색상

hole_color : 홀의 외곽선(내부 외곽선)의 색상

max_level : 외곽선을 그릴때 이동할 최대깊이

thicknessline_type : 외곽선의 굵기와 타입

offset : 외곽선이 그려질 위치를 지정하는 용도로 사용


#include <cv.h>

#include <highgui.h>

 

IplImage* g_image=NULL;

IplImage* g_gray=NULL;

IplImage* g_binary=NULL;

int g_thresh=100;

CvMemStorage* g_storage=NULL;

 

void on_trackbar(int pos) {

       

        if(g_storage==NULL) {

               g_gray=cvCreateImage(cvGetSize(g_image), 8, 1);

               g_binary=cvCreateImage(cvGetSize(g_image), 8, 1);

               g_storage=cvCreateMemStorage(0);

        } else {

               cvClearMemStorage(g_storage);

        }

 

        CvSeq* contours=0;

 

        //g_image영상을 BRG색공간을 그레이 스케일로 변환(BGR to Gray = BGR2GRAY)

        cvCvtColor(g_image, g_gray, CV_BGR2GRAY);

 

        //임계값 이하:0, 임계값초과값:1 설정

        cvThreshold(g_gray, g_gray, g_thresh, 255, CV_THRESH_BINARY);

        cvCopy(g_gray, g_binary);

 

        //윤곽선 찾기

        cvFindContours(

               g_gray,                //입력영상

               g_storage,             //검출된 외곽선을 기록하기 위한 메모리 스토리지

               &contours,             //외곽선의 좌표들이 저장된 Sequence

               sizeof(CvContour),    

               CV_RETR_TREE           //어떤종류의 외곽선 찾을지어떻게 보여줄지에 대한정보

        );     

 

        cvZero(g_gray);

        if(contours) {

               //외곽선을 찾은 정보(contour) 이용하여 외곽선을 그림

               cvDrawContours(

                       g_gray,                //외곽선이 그려질 영상

                       contours,              //외곽선 트리의 루트노드

                       cvScalarAll(255),      //외부 외곽선의 색상

                       cvScalarAll(128),      //내부 외곽선의 색상

                       100                    //외곽선을 그릴때 이동할 깊이

               );                           

        }

 

        cvShowImage("Original", g_image);

        cvShowImage("Binary", g_binary);

        cvShowImage("Contours", g_gray);

}

 

int main(int argcchar** argv) {

        if(argc!=2 || !(g_image=cvLoadImage(argv[1])))

               return -1;

 

        cvNamedWindow("Original", 1);

        cvNamedWindow("Binary", 1);

        cvNamedWindow("Contours", 1);

        cvCreateTrackbar("Threshold""Contours", &g_thresh, 255, on_trackbar);

        on_trackbar(0);

       

        cvWaitKey();

 

        cvReleaseImage(&g_image);

        cvReleaseImage(&g_gray);

        cvReleaseMemStorage(&g_storage);

        cvDestroyWindow("binary");

        cvDestroyWindow("Contours");

        return 0;

}


출력결과



반응형

'차근차근 > OpenCV' 카테고리의 다른 글

배경제거  (0) 2014.08.05
모멘트 - 외곽선의 유사도 비교  (0) 2014.08.05
메모리 스토리지  (0) 2014.08.05
임계값(Threshold)  (0) 2014.08.05
시퀀스(Sequence)  (0) 2014.08.05