如何使用openCV函数计算凸包面积?

4

我找不到一个可用的例子来使用OpenCV计算凸包的面积。我看到了一个使用cvApproxPoly和cvContourArea的例子,但是我无法让它工作。以下是我的代码。

IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );


int i, count = rand()%100 + 1;
CvPoint pt0;

CvPoint* points = (CvPoint*)malloc( count * sizeof(points[0]));
int* hull = (int*)malloc( count * sizeof(hull[0]));
CvMat point_mat = cvMat( 1, count, CV_32SC2, points );
CvMat hull_mat  = cvMat( 1, count, CV_32SC1, hull );        
for( i = 0; i < count; i++ )
{
    pt0.x = rand() % (img->width/2) + img->width/4;
    pt0.y = rand() % (img->height/2) + img->height/4;
    points[i] = pt0;
}


CvSeq* convex_hull=cvConvexHull2( &point_mat, &hull_mat, CV_CLOCKWISE, 0 );
5个回答

13
    vector<Point2f> originalPoints;   // Your original points
    vector<Point2f> convexHull;  // Convex hull points 
    vector<Point2f> contour;  // Convex hull contour points        
    double epsilon = 0.001; // Contour approximation accuracy

    // Calculate convex hull of original points (which points positioned on the boundary)
    convexHull(Mat(originalPoints),convexHull,false);

    // Approximating polygonal curve to convex hull
    approxPolyDP(Mat(convexHull), contour, 0.001, true);

    cout << fabs(contourArea(Mat(contour)));

2
我并不太明白将std::vector转换为cv::Mat的必要性:因为它们可以被convexHull、approxPolyDP和contourArea完美地处理。 - Antonio
@Pradeep Pati 感谢您的帮助,convexHull 和轮廓向量之间有什么区别?在我的情况下,它们始终是相同的点向量吗?据我所知,convexHull 本身就是多边形曲线,对吗? - Stav Bodik

6
实际上计算2D凸包的面积非常容易。你需要按顺时针方向从每个点开始,计算下方的面积。以下是一个简单的代码来完成这个任务。(前几行是凸包的定义和计算)
vector<Point2f> originalPoints;   // Your original points
vector<Point2f> ch;  // Convex hull points

// Calculate convex hull of original points (which points positioned on the boundary)
cv::convexHull(Mat(originalPoints),ch,false);
// false parameter is used to organize the points in clockwise direction

// Now calculate the area of sonvex hull 'ch':
double area = 0;
for (int i = 0; i < ch.size(); i++){
    int next_i = (i+1)%(ch.size());
    double dX   = ch[next_i].x - ch[i].x;
    double avgY = (ch[next_i].y + ch[i].y)/2;
    area += dX*avgY;  // This is the integration step.
}

area = abs(area); // 如果从右到左开始积分,则面积可能为负数。


你是对的,虽然(多亏了你),我找到了另一种计算二维凸包面积的方法。 - Gorayni

4

使用:

CvSeq* convex_hull=cvConvexHull2(&point_mat, &hull_mat, CV_CLOCKWISE, **1**); // 重点!

我的代码:

 CvMemStorage* storage = cvCreateMemStorage(0);
 CvSeq* contours = 0;
 cvFindContours(bordImage, storage, &contours, sizeof(CvContour),
            CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));

 for(CvSeq* seq = contours; seq != 0; seq = seq->h_next){
     cvDrawContours(dstImage, seq, CV_RGB(255,216,0), CV_RGB(0,0,250), 0, 1, 8);
 }

CvMemStorage* hullStorage = cvCreateMemStorage(0);
for(CvSeq* seq = contours; seq != 0; seq = seq->h_next){
    CvSeq *hulls = cvConvexHull2(seq, hullStorage, CV_CLOCKWISE, 1);
    cvDrawContours(dstImage, hulls, CV_RGB(255, 0, 0), CV_RGB(100, 0, 0), 0, 1, 8);
    for (int i = 0; i < hulls->total; i++) {
        CvPoint* p = (CvPoint*)cvGetSeqElem ( hulls, i );
         // ...
    }
    cvClearMemStorage(hullStorage);
}

1
在OpenCV 2.4.9中:
double computeConvexHullArea(vector<Point> originalPoints)
{
    vector<Point> hull;
    convexHull(originalPoints, hull);

    return contourArea(hull);
}

0

关于OpenCV Python:

hull = cv2.convexHull(cntr)  #cntr is the contour
convex_hull_area = cv2.contourArea(hull)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接