[OpenCV] 라벨링 – 2. 응용(connectedComponentsWithStats )

이전 글에서 라벨링에 대해 기초적인 내용을 알아보았습니다. 이번 글에서는 객체의 정보를 알아내는 방법에 대해 알아보겠습니다.

기존 문제점
라벨링

라벨링을 수행하여 객체의 개수를 파악하고 행렬에 객체의 번호를 부여하더라도 가공된 정보는 아닙니다.
객체의 영역이나 무게중심 좌표 등, 개발자가 행렬의 값을 일일히 대조하여 객체의 정보를 확인 하는 것은 좋지 않은 일입니다.

함수

OpenCV에서는 객체의 영역 정보를 얻어낼 수 있는 connectedComponentsWithStats 함수가 있습니다.

/**
@param image 입력 영상
@param labels 라벨 영상
@param stats 영역 정보를 담은 행렬
@param centroids 중심 정보를 담은 행렬
@param connectivity 연결성
@param ltype 출력 행렬 타입
*/
int connectedComponentsWithStats(InputArray image, OutputArray labels, OutputArray stats, OutputArray centroids, int connectivity = 8, int ltype = CV_32S);

connectedComponentsWithStats 함수를 통해 stats 정보와 centroids 정보를 얻을 수 있는데, stats는 객체의 영역정보, centroids는 무게중심에 대한 정보를 알 수 있습니다.

해당 정보에 대한 자세한 설명은 아래와 같습니다.

코드

위 내용을 코드로 보면 아래와 같습니다.

uchar data[] ={
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 255, 255, 0, 0, 0, 0, 0, 0, 0,
0, 255, 255, 0, 0, 0, 0, 0, 0, 0,
0, 255, 255, 0, 0, 255, 255, 255, 255, 0,
0, 255, 255, 0, 0, 255, 255, 255, 255, 0,
0, 255, 255, 0, 0, 0, 0, 255, 255, 0,
0, 0, 0, 0, 0, 0, 0, 255, 255, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 255, 255, 255, 255, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
Mat src = Mat(10, 10, CV_8UC1, data);


Mat labels, stats, centroids;
int iCount = connectedComponentsWithStats(src, labels, stats, centroids);

if (0 < iCount)
{
	cout << "============== stats ==============" << endl;
	int *pStats = stats.ptr<int>(0);
	cout << "배경 정보: x(" << pStats[0] << "), y(" << pStats[1] << "), width(" << pStats[2] << "), height(" << pStats[3] << "), area(" << pStats[4] << ")" << endl;
	for (int iRow = 1 ; iRow < iCount ; iRow++)
	{
		pStats = stats.ptr<int>(iRow);
		cout << "객체" << iRow << " 정보: x(" << pStats[0] << "), y(" << pStats[1] << "), width(" << pStats[2] << "), height(" << pStats[3] << "), area(" << pStats[4] << ")" << endl;
	}
    
    cout << endl << "============== centroids ==============" << endl;
	double *pCentroids = centroids.ptr<double>(0);
	cout << "배경 정보: 무게중심 x(" << pCentroids[0] << "), 무게중심 y(" << pCentroids[1] << ")" << endl;
	for (int iRow = 1 ; iRow < iCount ; iRow++)
	{
		pCentroids = centroids.ptr<double>(iRow);
		cout << "객체" << iRow << " 정보: 무게중심 x(" << pCentroids[0] << "), 무게중심 y(" << pCentroids[1] << ")" << endl;
	}
}

출력 결과는 아래와 같습니다.