C ++ - ObjC OpenCV约束Delaunay

时间:2011-11-23 01:19:18

标签: opencv triangulation delaunay convex-hull

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

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

但是,它不能很好地运作,因为有些三角形(例如,一个走路的人有两条腿的距离)'越过'一个洞

有没有人知道执行约束三角测量的方法。我想到了凸性缺陷,但无法理解如何开始这一点。

提前致谢!


事实上,它不是一个凸面的船体缺陷问题,而是一个三角形的问题。这张图片会告诉你麻烦:

http://img191.imageshack.us/img191/7527/capturedcran20111128180.png

特别是在三角形船体的底部,您可以看到三角测量位于轮廓中的AND中,因为OpenCV正在对凸包进行三角测量。我想找到一种方法来对轮廓本身进行三角测量。

我发现了一些关于在轮廓中添加Steiner点的想法,但找不到从OpenCV开始的位置。

我的想法是:

  • 测试三角形是否在轮廓中;
  • 如果为真:得到交点;
  • 并将其添加到cvSubdiv2D。

我是对的吗?

感谢您的耐心和答案!

2 个答案:

答案 0 :(得分:2)

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

http://img834.imageshack.us/img834/3373/capturedcran20111130143.png

这是结果(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。

答案 1 :(得分:1)

你必须使用:

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

这将返回CvConvexityDefect的序列(CvSeq),而不是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来查看它们是否在它们内部。 如果它们在缺陷内,则意味着它们位于主要轮廓之外。

希望这是你需要的东西,它会有所帮助。