2

我在 OpenCV 2.3.1 中成功实现了轮廓的 Delaunay 三角剖分。

使用 cvPointPolygonTest 我可以得到凸包中的所有三角形,然后我尝试在三角形质心上执行另一个 cvPointPolygonTest 以了解它们是否在主轮廓中,这样我就可以对轮廓进行约束三角剖分。

但是,它不能很好地工作,因为一些三角形(例如,一个走路的人,他的两条腿很远)“越过”一个洞

有谁知道执行约束三角测量的方法。我想到了convexityDefects,但无法理解如何从这个开始。

提前致谢 !


实际上,这不是凸包缺陷问题,而是三角剖分问题。这张图片会告诉你麻烦:

特别是在三角包的底部,您可以看到三角剖分在轮廓之内和之外,因为 OpenCV 正在对凸包进行三角剖分。我想找到一种方法来对轮廓本身进行三角测量。

我发现了一些关于在轮廓本身中添加 Steiner Points 的想法,但找不到从 OpenCV 开始的地方。

我的想法是:

  • 测试三角形是否在轮廓内和外;
  • 如果为真:获取交点;
  • 并将其添加到 cvSubdiv2D。

我说得对吗?

感谢您的耐心和您的回答!

4

2 回答 2

2

最后,我在我的程序中实现了 poly2tri 库。

这是结果(OpenCV 获取轮廓,然后 poly2tri 执行三角剖分):

// -------------------- poly2tri --------------------


NSMutableArray* temp = [[NSMutableArray alloc] init];

vector<p2t::Triangle*> triangles;
vector< vector<p2t::Point*> > polylines;
vector<p2t::Point*> polyline;

for(int i = 0; i < contour32->total; i++ ) {
    CvPoint2D32f* pt32 = CV_GET_SEQ_ELEM(CvPoint2D32f, contour32, i);
    polyline.push_back(new p2t::Point((double)pt32->x, (double)pt32->y));
}

polylines.push_back(polyline);


p2t::CDT* cdt = new p2t::CDT(polyline);



// TODO -> holes with CV_RETR_TREE

// Triangulation !
cdt->Triangulate();

// On exporte nos triangles
triangles = cdt->GetTriangles();

for (int i = 0; i < triangles.size(); i++) {

    p2t::Triangle& t = *triangles[i];
    p2t::Point& a = *t.GetPoint(0);
    p2t::Point& b = *t.GetPoint(1);
    p2t::Point& c = *t.GetPoint(2);

    double x1 = (width / rWidth * (double)a.x) - (width / 2.f);
    double y1 = (height / rHeight * (double)a.y) - (height / 2.f);                   
    double x2 = (width / rWidth * (double)b.x) - (width / 2.f);
    double y2 = (height / rHeight * (double)b.y) - (height / 2.f);
    double x3 = (width / rWidth * (double)c.x) - (width / 2.f);
    double y3 = (height / rHeight * (double)c.y) - (height / 2.f);

    [temp addObject:[[NSArray arrayWithObjects:
                      [NSArray arrayWithObjects:
                       [NSNumber numberWithDouble:x1],
                       [NSNumber numberWithDouble:y1],
                       [NSNumber numberWithDouble:0.],
                       nil], 
                      [NSArray arrayWithObjects:
                       [NSNumber numberWithDouble:x2],
                       [NSNumber numberWithDouble:y2],
                       [NSNumber numberWithDouble:0.],
                       nil], 
                      [NSArray arrayWithObjects:
                       [NSNumber numberWithDouble:x3],
                       [NSNumber numberWithDouble:y3],
                       [NSNumber numberWithDouble:0.],
                       nil], 
                      nil] autorelease]];

}

[outDelaunay addObject:temp];                       

其中contour32 是使用cvFindContours 找到的OpenCV 轮廓,然后转换为float32。

于 2011-11-30T13:32:35.427 回答
1

您将不得不使用:

    CvSeq* cvConvexityDefects(
const CvArr* contour,
const CvArr* convexhull,
CvMemStorage* storage = NULL
);

这将返回一个序列(CvSeq),CvConvexityDefect而不是 CvPoint 或您可能习惯的任何其他类似 CvSeq 的东西。

您可以循环处理缺陷,如下所示:

CvSeq* defects =  cvConvexityDefects(.....);
for (i = 0; i < defects->total; i++)
{
CvConvexityDefect* def = (CvConvexityDefect*)cvGetSeqElem(defects, i);
//do something with them
}

缺陷具有以下结构:

    typedef struct CvConvexityDefect {
// point of the contour where the defect begins
CvPoint* start;
// point of the contour where the defect ends
CvPoint* end;
// point within the defect farthest from the convex hull
CvPoint* depth_point;
// distance between the farthest point and the convex hull
float depth;
} CvConvexityDefect;

因此,在获得每个缺陷后,您可以从它们构建一个 CvSeq 点,并cvPointPolygonTest在三角形的质心上使用以查看它们是否在它们内部。如果它们在缺陷内部,则意味着它们在主要轮廓之外。

希望这是您所需要的并且对您有所帮助。

于 2011-11-23T13:50:18.803 回答