OpenCVでポリゴンの重心

出典: Wikimura

OpenCVでは、画像だけでなく、点列で表されたポリゴンのモーメントを求めることができる関数cvMomentsがある。 画像にも輪郭にも対応というのは、フラグを見て処理を変えているためかもしれない。

輪郭から重心を求める用途に使う前に、簡単な例で試した。 (画像がストライプに見えるのは、初期化していないため? とりあえず問題ないのでそのまま)

CvSeqを作る際、フラグCV_SEQ_POLYGONなどの輪郭を意味するフラグを使用しないと、cvMomentsでエラーが起こる。 このフラグについてはマニュアルに直接書かれていない。


 #include <stdio.h>
 #include <cv.h>
 #include <highgui.h>

 #define LINE_COLOR CV_RGB(255,0,0)
 #define CIRC_COLOR CV_RGB(0,0,255)

 int main( void)
 {
     CvMemStorage *storage = cvCreateMemStorage(0);
     CvSeq *seq = cvCreateSeq( CV_SEQ_POLYGON, sizeof( CvSeq), sizeof( CvPoint), storage);
     IplImage *img = cvCreateImage( cvSize( 200, 200), IPL_DEPTH_8U, 3);
     CvPoint p1, p2, p3, p4;
     CvPoint2D32f pc;
     CvMoments moment;

     p1 = cvPoint( 100, 100);
     p2 = cvPoint( 140, 120);
     p3 = cvPoint( 120, 100);
     p4 = cvPoint( 140,  80);

     cvSeqPush( seq, &p1);
     cvSeqPush( seq, &p2);
     cvSeqPush( seq, &p3);
     cvSeqPush( seq, &p4);

     cvMoments( seq, &moment);
     pc = cvPoint2D32f( moment.m10 / moment.m00, moment.m01 / moment.m00);

     cvDrawLine( img, p1, p2, LINE_COLOR, 2);
     cvDrawLine( img, p2, p3, LINE_COLOR, 2);
     cvDrawLine( img, p3, p4, LINE_COLOR, 2);
     cvDrawLine( img, p4, p1, LINE_COLOR, 2);
     cvDrawCircle( img, cvPointFrom32f( pc), 3, CIRC_COLOR, 2);

     cvNamedWindow( "img");
     cvShowImage( "img", img);

     printf("center: %.3f, %.3f\n", pc.x, pc.y);

     cvWaitKey( 0);

     cvReleaseImage( &img);
     cvReleaseMemStorage( &storage);
     cvDestroyAllWindows();
     return 0;
 }