OpenCV,C ++:Delaunay三角剖分中缺少三角形

时间:2012-05-12 13:49:54

标签: c++ opengl opencv triangulation delaunay

我在Ubuntu 11.04上使用NetBeans 7.1,并希望使用OpenCV从一组点中获取三角形。我按如下方式构建了Delaunay三角剖分。

vector< Triangle > CTwoDTriangulation::delaunayDiv(const vector< Point_<T> > & vP,   cv::Rect boundRect, vector<Triangle>& triangles, int& numTriangles)
{
    CvSubdiv2D* subdiv;
    int numPts=vP.size();
    CvPoint newPoint;

    CvMemStorage *storage;
    storage = cvCreateMemStorage(0);
    subdiv =  cvCreateSubdivDelaunay2D( boundRect, storage );
    for (size_t e = 0; e<numPts; e++)
    {
        newPoint=vP.at(e);
        if (newPoint.x>=boundRect.y && newPoint.y>=boundRect.y && newPoint.x<boundRect.width &&  newPoint.y<boundRect.height)
                cvSubdivDelaunay2DInsert(subdiv, vP.at(e));
    }

    CvSeqReader  reader;
    int i, total = subdiv->edges->total;
    int elem_size = subdiv->edges->elem_size;

    triangles.resize(2*total-5);    // Maximum number of triangles for number of edges
    numTriangles=0;

    cvStartReadSeq( (CvSeq*)(subdiv->edges), &reader, 0 );

    Triangle V;

    for( i = 0; i < total; i++ )
    {
        CvQuadEdge2D* edge = (CvQuadEdge2D*)(reader.ptr);

        if( CV_IS_SET_ELEM( edge ))
        {
            CvSubdiv2DEdge e = (CvSubdiv2DEdge)edge;
            if (FindTriangleFromEdge(e, V)) 
        {
            triangles.at(numTriangles++)=V;
        }
    }
    CV_NEXT_SEQ_ELEM( elem_size, reader );
}
cvReleaseMemStorage(&storage);

return triangles;
}

FindTriangleFromEdge()具有以下形式。

void CTwoDTriangulation::FindTriangleFromEdge(CvSubdiv2DEdge e, Triangle& V)
{
   CvSubdiv2DEdge t = e;    // Number of type size_t
   CvPoint buf[3];          // Triangle vertices
   int iPointNum = 3;
   int  j;
   CvPoint pts[3];

   for(j = 0; j < iPointNum; j++ )
   {
        CvSubdiv2DPoint* point = cvSubdiv2DEdgeOrg( t );
        if( !point ) break;
        pts[j].x=point->pt.x;
        pts[j].y=point->pt.y;
        buf[j] = cvPoint( cvRound(point->pt.x), cvRound(point->pt.y));
        t = cvSubdiv2DGetEdge( t, CV_NEXT_AROUND_LEFT );
   }
  AddTriangle(buf, pts, V);
}

这让我获得了大部分三角形但有些缺失了。例如,我设置了一组近似矩形网格的点。我得到以下内容 (5,1);(103101);(1101)
(106,1);(103101);(5,1)
(5,1);(106,1);(103101)
(204101);(106,1);(208,1)
(208,1);(307101);(204101)
(309,1);(307101);(204101)

所以(106,1);(204,1);(103,101)缺失,至少有一个三角形重复。

3 个答案:

答案 0 :(得分:1)

您的if语句似乎有错误吗?为什么要将newPoint.x与boundRect.y进行比较?

if (newPoint.x>=boundRect.y && newPoint.y>=boundRect.y && newPoint.x<boundRect.width &&  newPoint.y<boundRect.height)
            cvSubdivDelaunay2DInsert(subdiv, vP.at(e));

答案 1 :(得分:0)

我遇到了同样的问题。我的解决方案是检查

cvSubdiv2DGetEdge(t,CV_NEXT_AROUND_RIGHT);

看!有了它,它发现了失踪者,但却错过了其他一些人。所以我的解决方案是现在结合两种结果。

答案 2 :(得分:0)

当您使用CV_NEXT_AROUND_LEFT时,要选择的下一条边将是指定边的左侧面上的边。现在考虑,例如,由顶点V1V2V3形成的三角形,其边为Edge1Edge2Edge3

此外,假设V1Edge1的组织点,V2Edge2的组织点,V3是组织点{ {1}}(如同以顺时针方向连接的矢量)。在这种情况下,左小平面总是在给定三角形之外,因此,在您的代码中,此三角形将丢失。

除了将Edge3CV_NEXT_AROUND_LEFT合并并删除将要记录的重复三角形之外,我无法实现另一种阻止此方法。