이전 글에서 findContours 함수를 이용하여 외곽선을 검출하였습니다.
이렇게 검출한 외곽선 정보에서 객체의 위치, 크기 등의 정보를 추출하는 방법에 대해서 알아보겠습니다.
객체를 감싸는 사각형, 원 구하는 함수
함수부터 빠르게 알아보겠습니다.
외곽선 정보에서 바운딩 박스를 구하기 위해서 boundingRect 함수를 사용합니다.
/**
@param array 외곽선 정보
*/
Rect boundingRect( InputArray array );
객체를 최소한으로 감싸는 사각형을 구하는 함수는 minAreaRect 함수 입니다.
/**
@param points 외곽선 정보
*/
RotatedRect minAreaRect( InputArray points );
객체를 최소한으로 감싸는 원을 구하는 함수는 minEnclosingCircle 함수 입니다.
/**
@param points 외곽선 정보
@param center 원의 중심 좌표 반환
@param radius 원의 반지름 반환
*/
void minEnclosingCircle( InputArray points, CV_OUT Point2f& center, CV_OUT float& radius );
샘플 코드는 아래와 같습니다.
Mat src = imread("alphabet_d.png", IMREAD_GRAYSCALE);
if (src.empty())
{
cerr << "image open error" << endl;
return -1;
}
vector<vector<Point>> contours;
findContours(src, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
Mat dst;
cvtColor(src, dst, COLOR_GRAY2BGR);
for (int iIndex = 0 ; iIndex < contours.size() ; iIndex++)
{
vector<Point> pnts = contours.at(iIndex);
// 바운딩 박스
Rect rc = boundingRect(pnts);
rectangle(dst, rc, Scalar(rand() % 256, rand() % 256, rand() % 256), 2);
// 회전된 사각형 - 제일 작은 영역의 사각형 반환
RotatedRect rotated_rc = minAreaRect(contours.at(iIndex));
Point2f pnt_rc[4];
rotated_rc.points(pnt_rc);
Scalar scalar = Scalar(rand() % 256, rand() % 256, rand() % 256);
for (int i = 0; i < 4; i++)
line(dst, pnt_rc[i], pnt_rc[(i+1)%4], scalar, 2);
// 최소 크기 원
Point2f pnt_circle;
float radius;
minEnclosingCircle(pnts, pnt_circle, radius);
circle(dst, pnt_circle, radius, Scalar(rand() % 256, rand() % 256, rand() % 256), 2);
}
imshow("src", src);
imshow("dst", dst);
waitKey();
destroyAllWindows();
실행 결과는 아래와 같습니다.
면적 구하기
외곽선의 면적을 구하는 함수는 contourArea 함수 입니다. 폐곡선 형태로 이루어진 외곽선의 면적을 반환합니다.
/**
@param contour 외곽선 정보
@param oriented true: 곡선 진행 방향에 따라 부호 값이 달라짐. false: 절대적인 면적값 반환
*/
double contourArea( InputArray contour, bool oriented = false );
샘플 코드는 아래와 같습니다.
Mat src = imread("alphabet_d.png", IMREAD_GRAYSCALE);
if (src.empty())
{
cerr << "image open error" << endl;
return -1;
}
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(src, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE);
Mat dst;
cvtColor(src, dst, COLOR_GRAY2BGR);
for (int iIndex = 0 ; iIndex < contours.size() ; iIndex++)
{
vector<Point> pnts = contours.at(iIndex); // 외곽선 정보
double area = contourArea(pnts); // 면적 구하기
String strArea = format("%g", area);
Scalar scalar = Scalar(rand() % 256, rand() % 256, rand() % 256);
drawContours(dst, contours, iIndex, scalar, -1, LINE_8, hierarchy);
putText(dst, strArea, Point(0, 50), FONT_HERSHEY_SIMPLEX, 2, scalar);
}
imshow("src", src);
imshow("dst", dst);
waitKey();
destroyAllWindows();
아래는 실행 결과입니다.