2011-08-10 12:28:01 +02:00
|
|
|
#include <opencv2/imgproc/imgproc.hpp>
|
|
|
|
#include <opencv2/highgui/highgui.hpp>
|
2011-08-09 17:11:32 +02:00
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
using namespace cv;
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
static void help()
|
|
|
|
{
|
2012-06-15 15:04:17 +02:00
|
|
|
cout << "\nThis program demostrates iterative construction of\n"
|
2011-08-09 17:11:32 +02:00
|
|
|
"delaunay triangulation and voronoi tesselation.\n"
|
|
|
|
"It draws a random set of points in an image and then delaunay triangulates them.\n"
|
|
|
|
"Usage: \n"
|
|
|
|
"./delaunay \n"
|
|
|
|
"\nThis program builds the traingulation interactively, you may stop this process by\n"
|
|
|
|
"hitting any key.\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_subdiv_point( Mat& img, Point2f fp, Scalar color )
|
|
|
|
{
|
|
|
|
circle( img, fp, 3, color, CV_FILLED, 8, 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_subdiv( Mat& img, Subdiv2D& subdiv, Scalar delaunay_color )
|
|
|
|
{
|
2011-08-10 12:28:01 +02:00
|
|
|
#if 1
|
2011-08-09 17:11:32 +02:00
|
|
|
vector<Vec6f> triangleList;
|
|
|
|
subdiv.getTriangleList(triangleList);
|
|
|
|
vector<Point> pt(3);
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
for( size_t i = 0; i < triangleList.size(); i++ )
|
|
|
|
{
|
|
|
|
Vec6f t = triangleList[i];
|
|
|
|
pt[0] = Point(cvRound(t[0]), cvRound(t[1]));
|
|
|
|
pt[1] = Point(cvRound(t[2]), cvRound(t[3]));
|
|
|
|
pt[2] = Point(cvRound(t[4]), cvRound(t[5]));
|
|
|
|
line(img, pt[0], pt[1], delaunay_color, 1, CV_AA, 0);
|
|
|
|
line(img, pt[1], pt[2], delaunay_color, 1, CV_AA, 0);
|
|
|
|
line(img, pt[2], pt[0], delaunay_color, 1, CV_AA, 0);
|
|
|
|
}
|
2011-08-10 12:28:01 +02:00
|
|
|
#else
|
|
|
|
vector<Vec4f> edgeList;
|
|
|
|
subdiv.getEdgeList(edgeList);
|
|
|
|
for( size_t i = 0; i < edgeList.size(); i++ )
|
|
|
|
{
|
|
|
|
Vec4f e = edgeList[i];
|
|
|
|
Point pt0 = Point(cvRound(e[0]), cvRound(e[1]));
|
|
|
|
Point pt1 = Point(cvRound(e[2]), cvRound(e[3]));
|
|
|
|
line(img, pt0, pt1, delaunay_color, 1, CV_AA, 0);
|
|
|
|
}
|
|
|
|
#endif
|
2011-08-09 17:11:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void locate_point( Mat& img, Subdiv2D& subdiv, Point2f fp, Scalar active_color )
|
|
|
|
{
|
|
|
|
int e0=0, vertex=0;
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
subdiv.locate(fp, e0, vertex);
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
if( e0 > 0 )
|
|
|
|
{
|
|
|
|
int e = e0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Point2f org, dst;
|
|
|
|
if( subdiv.edgeOrg(e, &org) > 0 && subdiv.edgeDst(e, &dst) > 0 )
|
|
|
|
line( img, org, dst, active_color, 3, CV_AA, 0 );
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
e = subdiv.getEdge(e, Subdiv2D::NEXT_AROUND_LEFT);
|
|
|
|
}
|
|
|
|
while( e != e0 );
|
|
|
|
}
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
draw_subdiv_point( img, fp, active_color );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-15 15:04:17 +02:00
|
|
|
static void paint_voronoi( Mat& img, Subdiv2D& subdiv )
|
2011-08-09 17:11:32 +02:00
|
|
|
{
|
|
|
|
vector<vector<Point2f> > facets;
|
2011-08-10 12:28:01 +02:00
|
|
|
vector<Point2f> centers;
|
|
|
|
subdiv.getVoronoiFacetList(vector<int>(), facets, centers);
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
vector<Point> ifacet;
|
|
|
|
vector<vector<Point> > ifacets(1);
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
for( size_t i = 0; i < facets.size(); i++ )
|
|
|
|
{
|
|
|
|
ifacet.resize(facets[i].size());
|
|
|
|
for( size_t j = 0; j < facets[i].size(); j++ )
|
|
|
|
ifacet[j] = facets[i][j];
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
Scalar color;
|
2011-08-10 12:28:01 +02:00
|
|
|
color[0] = rand() & 255;
|
|
|
|
color[1] = rand() & 255;
|
|
|
|
color[2] = rand() & 255;
|
2011-08-09 17:11:32 +02:00
|
|
|
fillConvexPoly(img, ifacet, color, 8, 0);
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
ifacets[0] = ifacet;
|
|
|
|
polylines(img, ifacets, true, Scalar(), 1, CV_AA, 0);
|
2011-08-10 12:28:01 +02:00
|
|
|
circle(img, centers[i], 3, Scalar(), -1, CV_AA, 0);
|
2011-08-09 17:11:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main( int, char** )
|
|
|
|
{
|
|
|
|
help();
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
Scalar active_facet_color(0, 0, 255), delaunay_color(255,255,255);
|
|
|
|
Rect rect(0, 0, 600, 600);
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
Subdiv2D subdiv(rect);
|
|
|
|
Mat img(rect.size(), CV_8UC3);
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
img = Scalar::all(0);
|
|
|
|
string win = "Delaunay Demo";
|
|
|
|
imshow(win, img);
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
for( int i = 0; i < 200; i++ )
|
|
|
|
{
|
|
|
|
Point2f fp( (float)(rand()%(rect.width-10)+5),
|
|
|
|
(float)(rand()%(rect.height-10)+5));
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
locate_point( img, subdiv, fp, active_facet_color );
|
|
|
|
imshow( win, img );
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
if( waitKey( 100 ) >= 0 )
|
|
|
|
break;
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
subdiv.insert(fp);
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
img = Scalar::all(0);
|
|
|
|
draw_subdiv( img, subdiv, delaunay_color );
|
|
|
|
imshow( win, img );
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
if( waitKey( 100 ) >= 0 )
|
|
|
|
break;
|
|
|
|
}
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
img = Scalar::all(0);
|
|
|
|
paint_voronoi( img, subdiv );
|
|
|
|
imshow( win, img );
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
waitKey(0);
|
2012-06-15 15:04:17 +02:00
|
|
|
|
2011-08-09 17:11:32 +02:00
|
|
|
return 0;
|
|
|
|
}
|