내맘대로 공부기록.

[ C++ ]

[ openCV | C++ ] findContours 함수 사용법, 입력 출력(포인트) 값의 이해

fwanggus 2021. 2. 23. 21:53
반응형


🔗  함수와 매개변수 : findContours(매개변수입력)

🔗  DEMO.

       🖼  이미지 이진화 하기

       😷  HSV 이미지 마스킹 하기

       📏  컨투어 찾기



 

이진화(Binary) 이미지 소스로 부터 사물의 외곽 형상을 검출하여, 사물인식에 사용될 수 있습니다. 여기서 이진화 이미지는 GRAY SCALE 또는 HSV SPACE 색으로 변환된 이미지에 대해서 적용 될 수 있습니다.

 

GRAY SCALE, HSV SPACE 이미지 변환은 아래 글을 참고 부탁드립니다.

 

[ openCV | C++ ] 머신비전 이해를 위한 openCV 기초 리뷰

🙋🏻‍♂️ openCV를 시작하면서, 무(無) 일 때 openCV의 느낌? 📋 튜토리얼 시작 📏 이미지 리사이징 🖼 이미지 변환  1. 그레이 스케일링  2. HSV 스케일링  ⭕️ 엣지검출  1. 블러(Blur) 처리  2.

fwanggu-lee.tistory.com

 

함수는 아래 헤더파일에서 불러올 수 있습니다.

#include <opencv2/imgproc.hpp>

 

🔗  함수와 매개변수 : findContours(매개변수입력)

TYPE

VARIABLE

InputOutputArray 

image

OutputArrayOfArrays 

contours

OutputArray 

hierarchy

int 

mode

int 

method

Point 

offset = Point() 

 

이 함수를 사용하기 위해 중요한 부분은 입력, 출력 값인 것 같은데요. 이진화된 이미지를 입력 받아, 이미지의 contours 정보를 contours 어레이에 그 정보(Point 좌표)를 담아주는 형태입니다.

 

🔗  DEMO.

간단한 예를 통해서, 어떤 정보를 저장하는지 확인해보겠습니다. 

먼저 이진화된 이미지를 생성한 후, 해당 이미지를 findContours 함수에 적용시켜 컨투어 데이터 확인하면 될 것 같습니다.  색깔과 모양을 다르게 해서 아래와 같이 이미지를 준비했습니다.


 

초기 이미지 준비.

 

 

🖼  이미지 이진화 하기

BGR SPACE → HSV SPACE : cvtColor함수를 이용해 Color Space를 변환(COLOR_BGR2HSV)

    Mat img,imgHSV;
    Mat mask;
    
    string data = "FILE PATH...";
    img = imread(data);
    cvtColor(img, imgHSV, COLOR_BGR2HSV);

 

HSV Space로 단순히 변환한 결과는 아래와 같습니다. 

 

 

HSV Space 로 변화된 이미지.

 

 

😷  HSV 이미지 마스킹 하기( inRange함수 사용 )

초기 이미지에서 보라색 삼각형을 마스킹하는, HSV(Hue, Saturation, Value)의 최대 최소 경계 값을 미리 찾아놨습니다.

 

// hmin, smin, vmin, hmax, smax, vmax
114,174,224,151,255,255

 

inRange 함수로 마스킹 적용하기.(mask 변수에 마스킹이 적용됩니다.)

    int hmin=114;
    int smin=174;
    int vmin=224;
    int hmax=151;
    int smax=255;
    int vmax=255;

    Scalar lower(hmin,smin,vmin);
    Scalar upper(hmax,smax,vmax);
    inRange(imgHSV, lower, upper, mask);

 

이 작업은 colorPicker 프로젝트를 이용했습니다. HSV Space로 변화된 이미지에서 HSV 각 요소의 최대, 최소 값을 조절하면서 타겟이 되는 색(사물인식 대상)의 HSV값을 찾아가는 작업입니다. 타겟 대상은 하얗게 표시되며, 나머지 배경은 검정색으로 나타나게 됩니다. 

 

 

마스킹 성공.

 

 

colorPicker의 전체 코드는 여기(깃헙)에서 확인할 수 있습니다. colorPicker에  대한 포스팅은 작성 후 링크를 걸어 놓을게요. 

 

📏  컨투어 찾기

입력된 (이진화된)이미지에서 외곽 테두리를 찾습니다.

    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    
    // 소스 이미지로 부터 윤곽선을 찾고, contour 벡터 안에 Point정보를 저장한다.
    findContours(mask, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

입력한 매개변수의 간단 설명

mask           : mask 처리된 이미지 소스를 입력
contours     : 각 도형의 윤관석을 표현하는 포인트 요소를 벡터로 표현해서 가지고 있게 된다.
hierarchy    : 4개 정수형 데이터 요소로 이미지 토폴로지 정보를 저장한다.(optional)

 

vector<Point> : Point 객체를 요소로 갖는 벡터(어레이)를 선언. x,y 좌표 데이터가 한 셋트가 되어 저장된다.
vector<vector<Point>> : 위의 x,y 좌표 데이터 셋트를 한 요소로, 컨투어를 표현하는 점들의 집합이 되게 된다.

 

마지막 두 변수는(RETR_EXTERNAL, CHAIN_APPROX_SIMPLE) 차례대로 mode, method(approximation) 를 지정할 수 있으며, 공식문서의 기본적인 내용을 참고했습니다.


contours 벡터를 선언하는 것이 중요하며, 컨투어의 요소는 포인트 타입으로 받아오게 되며, 여러개의 컨투어를 동시에 추출할 수 있기 때문에 어레이의 어레이 형태로 벡터를  선언해주었습니다. 

 

보라색 삼각형을  타겟으로 했으며, 해당 삼각형을 감싸는 테두리 좌표를 반환해주게 됩니다. 해당 내용을 터미널에서 확인해 보기 위해 아래와 같이 코드를 작성했습니다. 예상내용으로는 컨투어 요소는 삼각형 1개일 것이며, 1개 컨투어를 구성하고 있는 점들의 갯수는 출력해봐야 알 것 같습니다.

 

    cout << "contour size : " << contours.size() << endl;

 

🔄  코드 실행결과

 

 

컨투어 갯수는 1개.

 

 

컨투어 갯수가 확인 되었기 때문에, 해당 컨투어를 구성하는 점의 갯수를 확인해보겠습니다.

다음과 같이 코드를 추가해주세요.

 

    // 컨투어 갯수가 1개였기 때문에 첫번째 요소인 0번째 멤버를 선택해서 출력한다.
    cout << "contour Point size : " << contours[0].size() << endl;
    for(int i=0;i<contours[0].size();i++){
        cout << i+1 << "th POINT COORD. : " << contours[0][i] << endl;
    }

 

🔄  코드 실행결과 : 포인트의 갯수느 174개로 확인했으며, [x,y] 좌표 형태로 출력됨을 알 수 있습니다.

 

 

컨투어 갯수 및 컨투어를 구성하는 포인트 데이터 출력.

 

 

(이 글에서는 다루지 않겠지만) 컨투어의 포인트 데이터는 커브데이터로 근사화 시킬수 있으며, 최종적으로 물체를 식별해 내는 작업으로 활용할 수 있습니다. 이상 끝.

 

🚀 이 글도 참고 해보세요.

 

[ openCV | C++ ] approxPolyDP 함수 사용 방법.

어떤 함수 ❓ 🤔 "형상을 근사" 하는 함수입니다. 검출된 형상을 표현하기 위해, 점 데이터가 사용되어지는데요. 그 데이터 수를 수많은 점 데이터 군집에서, 보다 적은 점으로 커브 또는 다각

fwanggu-lee.tistory.com

 

반응형