본문 바로가기

프로그래밍

[OpenCV] Ball tracking

공을 트래킹하는 방법은 공의 색상을 이용하거나 고정된 화면에서 공을 추적하는 경우는 이전 프레임과의 비교를 통해 공을 추적한다.


공 트래킹을 위한 관련 메쏘드들을 정리한다.




원본이미지

cv::Mat image = cv::imread(filename, 0);


리사이즈

cv::Mat frame = cv::resize(image, (500, 500));



HSV 색상변환

cv::Mat hsv_image

cv::cvtColor( frame, hsv_image, cv::COLOR_BGR2HSV );



특정 색상 값을 마스크로 사용 : 색상 기반 트래킹

cv::Mat mask;

cv::inRange( hsy_image, cv::Scalar(160,100,100), cv::Scalar(179,255,255), mask);



기타 색상 hsy 정보

녹색 : (29,86,6), (64,255,255)

빨강 : (160,100,100),(179,255,255)



이전 프레임과의 비교 사용 : 변화량 기반 트래킹

cv::Mat mask;

cv::absdiff( current_frame, prev_frame, mask );





Threshold 마스크 생성 

마스크 적용된 이미지에 특정 값에 미치지 못하는 값들을 처리하기위해 threshold 를 적용해 준다.

각 픽셀 값을 loop 를 돌며 값을 비교해도 되나 threshold 함수를 사용해 간단히 처리 가능하다.


cv::Mat gray_image = cv::cvtColor( frame, gray_image, cv::COLOR_BGR2GRAY);


Mat mask;

int minSaturation = 20; // 0 이상값으로 20~30 정도의 값

cv::threshold( gray_image, mask, minSaturation, 255, cv::THRESH_BINARY);




모폴로지 : 작은 오브젝트들 제거용 필터

보통 threshold를 적용하면 원하는 객체의 모양을 얻을 수 있는데, IR 카메라 소스나 저조도 환경에서 촬영된 이미지는 노이즈를 제거할 필요가 있다.


연산 순서에 따라 

erode-dilate = 작은 노이즈제거

dilate-erode = 작은 객체들을 합침


모폴로지 매트릭스 마스크 생성 매쏘드

MORPH_RECT

MORPH_ELLIPSE

MORPH_CROSS



모폴로지 원형 마스크 적용 : src 매트릭스에 모폴로지 적용 후 mask 매트릭스로 반환해 준다.

cv::Mat work;

cv::Mat mask;

cv::erode( frame, work, getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5)) );

cv::dilate( work, mask, getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5)) );



중심점(Point(-1,-1))과 반복횟수(3) 를 적용해 보다 세부적인 설정이 가능하다.

cv::dilate( frame, work, getStructuringElement(cv::MORPH_ELLIPSE, Size(5,5)) , cv::Point(-1,-1), 3 );

cv::erode( work, mask, getStructuringElement(cv::MORPH_ELLIPSE, Size(5,5)), cv::Point(-1,-1), 3 );




Blur : 표시되는 오브젝트가 너무 작은 경우 블러 처리해 크기가 조금 늘어 나도록 한다.

cv::blur( frame, mask, cv::Size( 10, 10));


Threshold 추가 : blur 이후에는 객체가 흐릿해지므로 thershold 로 좀더 명확히 해준다.





윤곽 찾기

findContours

이것저것 마스크가 적용된 이미지에서 윤곽을 찾는다. 

vector<cv::Mat> contours;

cv::findContours( mask, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point(0,0) );




Canny : 정밀한 윤곽 검출용

Mat canny_output;

vector<vector<Point>> contours;

vector<Vec4i> hierarchy;

int threshold = 100;

Canny( gray_image, canny_output, threshold, threshold*2 , 3);

findContours( canny_output, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPPROX_SIMPLE, cv::Point(0,0));




윤곽에서 바운딩 박스 찾기


for( int i=0; i<contours.size(); i++)

{

Point2f center;

float radius;

Rect rect;

Point2f points[4];

RotatedRect rotate_rect;


// 사각 영역

rect = boundingRect(contours[i]);


// 회전영역(최소 영역)

rotate_rect = minAreaRect(contours[i]);


// 원형 영역

minEnclosingCircle(contours[i], center, radius);


// 회전영역 정보를 좌표로 변환

rotate_rect.point(points);


// 회전영역 폴리곤으로 표시

vector<vector<Point>> polylines;

polylines.resize(1);

for( int j=0;j<4; j++)

{

polylines[0].push_back(points[j]);

}



// 모양별 그리기

rectangle( bounding_mat, rect, Scalar(0,0,255), 2);

polylines( bounding_mat, polylines, true, Scalar(0, 255, 0), 2);

circle(bounding_mat, center, radius, Scalar(255, 0, 0 ), 2);

}





'프로그래밍' 카테고리의 다른 글

[COCOS2D-X] cocos2d-x 3.0 Eclipse 설정  (0) 2014.05.03
유니코드 관련 일부 정리....  (1) 2013.11.21