opencv Delaunay三角剖分例子

来源:互联网 发布:淘宝虚假交易处罚 编辑:程序博客网 时间:2024/06/10 05:02

一、Delaunay三角剖分(Delaunay Triangulation)相关知识

http://www.cnblogs.com/soroman/archive/2007/05/17/750430.html

上述连接博客上原理写的比较清楚,个人觉得在opencv中也是采用随机增量法(Incremental),博主的代码也很赞。
但是opencv中采用的描述Delaunay的数据结构和博主的方法不一样。

对opencv中描述Delaunay数据结构及其函数描述比较详细的可以参考以下网站

http://www.vckbase.com/document/viewdoc/?id=1794

 

随机增量法描述:http://www.karlchenofhell.org/cppswp/lischinski.pdf

贴个图,方便理解

二、opencv 代码

#pragma comment(lib,"cxcore210d.lib")
#pragma comment(lib,"highgui210d.lib")
#pragma comment(lib,"cv210d.lib")
#pragma comment(lib,"cvaux210d.lib")

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


#define  voronoi_color  CV_RGB(0,255,255)
#define  delaunay_color  CV_RGB(100,0,255)

void draw_subdiv_edge( IplImage* img, CvSubdiv2DEdge edge, CvScalar color );
void draw_subdiv_facet( IplImage* img, CvSubdiv2DEdge edge );

int main(int argc,char ** argv)
{
 CvPoint2D32f fp[] = {
  107, 64,
  172, 62,
  102, 107,
  126, 106,
  157, 108,
  182, 106,
  142, 156,
  134, 167,
  148, 167,
  123, 203,
  161, 202,
  142, 253,
  63, 166,
  209, 159,
  141, 80,
  141, 108
 };
 CvRect rect={0,0,600,600};
 int i;
 CvMemStorage *storage;
 storage=cvCreateMemStorage(0);
 CvSubdiv2D * subdiv;
 subdiv=cvCreateSubdiv2D(CV_SEQ_KIND_SUBDIV2D,sizeof(*subdiv),sizeof(CvSubdiv2DPoint),
  sizeof(CvQuadEdge2D),storage);
 cvInitSubdivDelaunay2D(subdiv,rect);
 for (i=0;i<16;i++)
 {
  cvSubdivDelaunay2DInsert(subdiv,fp[i]);
 }
 cvCalcSubdivVoronoi2D(subdiv);//计算Vornoi划分

 //画图
 IplImage * img=cvCreateImage(cvSize(600,600),8,3);
 cvSet(img,cvScalar(255,255,255,0));
 IplImage * img2=cvCreateImage(cvSize(600,600),8,3);
 cvSet(img2,cvScalar(255,255,255,0));
 CvSeqReader reader;
 int  total=subdiv->edges->total;
 int elem_size=subdiv->edges->elem_size;

 cvStartReadSeq((CvSeq *)(subdiv->edges),&reader,0);
 for (i=0;i<total;i++)
 {
  CvQuadEdge2D * edge=(CvQuadEdge2D *)(reader.ptr);
  if (CV_IS_SET_ELEM(edge))
  {
   draw_subdiv_edge( img, (CvSubdiv2DEdge)edge + 1, voronoi_color );
   draw_subdiv_edge( img, (CvSubdiv2DEdge)edge, delaunay_color );
   draw_subdiv_facet(img2,cvSubdiv2DRotateEdge( (CvSubdiv2DEdge)edge, 1 ));//cvSubdiv2DRotateEdge(

//(CvSubdiv2DEdge)edge, 1 )  ===(CvSubdiv2DEdge)edge + 1
   draw_subdiv_facet(img2,cvSubdiv2DRotateEdge( (CvSubdiv2DEdge)edge, 3 ));//其次,因为在Delaunay划分中,所有边//

//是有方向的,光通过e进行轮循可能会遗失部分三角形,因此同时还得以e的反向边进行轮循
  }
  CV_NEXT_SEQ_ELEM( elem_size, reader );
 }
 for (i=0;i<16;i++)
 {
  cvLine(img,cvPoint(cvRound(fp[i].x),cvRound(fp[i].y)),cvPoint(cvRound(fp[i].x),
   cvRound(fp[i].y)),CV_RGB(255,0,0),2,8);
 }
 cvNamedWindow("Delaunay",1);
 cvShowImage("Delaunay",img);
 cvNamedWindow("Voronoi",1);
 cvShowImage("Voronoi",img2);
 cvWaitKey();
 cvDestroyWindow("Delaunay");
 cvDestroyWindow("Voronoi");
 cvReleaseImage(&img);
 cvReleaseImage(&img2);
}

void draw_subdiv_edge( IplImage* img, CvSubdiv2DEdge edge, CvScalar color )
{
 CvSubdiv2DPoint* org_pt;
 CvSubdiv2DPoint* dst_pt;
 CvPoint2D32f org;
 CvPoint2D32f dst;
 CvPoint iorg, idst;

 org_pt = cvSubdiv2DEdgeOrg(edge);
 dst_pt = cvSubdiv2DEdgeDst(edge);

 if( org_pt && dst_pt )
 {
  org = org_pt->pt;
  dst = dst_pt->pt;

  iorg = cvPoint( cvRound( org.x ), cvRound( org.y ));
  idst = cvPoint( cvRound( dst.x ), cvRound( dst.y ));

  cvLine( img, iorg, idst, color, 1, CV_AA, 0 );
 }
}

void draw_subdiv_facet( IplImage* img, CvSubdiv2DEdge edge )
{
 CvSubdiv2DEdge t = edge;
 int i, count = 0;
 CvPoint* buf = 0;

 // count number of edges in facet
 do
 {
  count++;
  t = cvSubdiv2DGetEdge( t, CV_NEXT_AROUND_LEFT );
 } while (t != edge );

 buf = (CvPoint*)malloc( count * sizeof(buf[0]));

 // gather points
 t = edge;
 for( i = 0; i < count; i++ )
 {
  CvSubdiv2DPoint* pt = cvSubdiv2DEdgeOrg( t );
  if( !pt ) break;
  buf[i] = cvPoint( cvRound(pt->pt.x), cvRound(pt->pt.y));
  t = cvSubdiv2DGetEdge( t, CV_NEXT_AROUND_LEFT );
 }

 if( i == count )
 {

  CvSubdiv2DPoint* pt = cvSubdiv2DEdgeDst( cvSubdiv2DRotateEdge( edge, 1 ));
  cvFillConvexPoly( img, buf, count, CV_RGB(rand()&255,rand()&255,rand()&255), CV_AA, 0 );
  cvPolyLine( img, &buf, &count, 1, 1, CV_RGB(0,0,0), 1, CV_AA, 0);
  cvLine( img, cvPoint(pt->pt.x,pt->pt.y),cvPoint(pt->pt.x,pt->pt.y), CV_RGB(255,0,0),3);
 }
 free( buf );
}

 

平台:opencv2.1 vs2008

实验结果:

0 0
原创粉丝点击