공을 트래킹하는 방법은 공의 색상을 이용하거나 고정된 화면에서 공을 추적하는 경우는 이전 프레임과의 비교를 통해 공을 추적한다.
공 트래킹을 위한 관련 메쏘드들을 정리한다.
원본이미지
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 |