应用:人脸检测的核心技术
代码:
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <fstream>
using namespace cv;
using namespace std;
static void help()
{
cout << "\nThis program demonstrates iterative construction of\n"
"delaunay triangulation and voronoi tessellation.\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 triangulation 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, FILLED, LINE_8, 0 );
}
//画出三角剖分的边
static void draw_subdiv( Mat& img, Subdiv2D& subdiv, Scalar delaunay_color )
{
#if 1
vector<Vec6f> triangleList;
subdiv.getTriangleList(triangleList);
vector<Point> pt(3);
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, LINE_AA, 0);
line(img, pt[1], pt[2], delaunay_color, 1, LINE_AA, 0);
line(img, pt[2], pt[0], delaunay_color, 1, LINE_AA, 0);
}
#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, LINE_AA, 0);
}
#endif
}
//画出voronoi面
static void paint_voronoi( Mat& img, Subdiv2D& subdiv )
{
vector<vector<Point2f> > facets;
vector<Point2f> centers;
subdiv.getVoronoiFacetList(vector<int>(), facets, centers);
vector<Point> ifacet;
vector<vector<Point> > ifacets(1);
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];
Scalar color;
color[0] = rand() & 255;
color[1] = rand() & 255;
color[2] = rand() & 255;
fillConvexPoly(img, ifacet, color, 8, 0);
ifacets[0] = ifacet;
polylines(img, ifacets, true, Scalar(), 1, LINE_AA, 0);
circle(img, centers[i], 3, Scalar(), FILLED, LINE_AA, 0);
}
}
int main( int argc, char** argv )
{
cv::CommandLineParser parser(argc, argv, "{help h||}");
if (parser.has("help"))
{
help();
return 0;
}
Scalar active_facet_color(0, 0, 255), delaunay_color(255,255,255);
Mat img = imread("tt.jpg");
Mat img_ori = img.clone();
Size size = img.size();
Rect rect(0, 0,size.width,size.height);//外接边界盒子
Subdiv2D subdiv(rect);//细分
string win = "Delaunay Demo";
//点集
vector<Point2f> points;
std::ifstream ifs("face.txt");
int x, y;
while(ifs >> x >>y)
{
points.push_back(Point2f(x,y));
}
for( vector<Point2f>::iterator it = points.begin(); it != points.end(); it++)
{
subdiv.insert(*it);
Mat img_copy = img_ori.clone();
// 画三角剖分
draw_subdiv( img_copy, subdiv, delaunay_color );
imshow(win, img_copy);
waitKey(1000);
}
draw_subdiv( img, subdiv, delaunay_color );
//画点
for( vector<Point2f>::iterator it = points.begin(); it != points.end(); it++)
{
draw_subdiv_point(img, *it, active_facet_color);
}
Mat img_voronoi = Mat::zeros(img.rows, img.cols, CV_8UC3);
paint_voronoi( img_voronoi, subdiv );
imshow(win, img_voronoi );
waitKey(0);
return 0;
}
效果:

