当评价一个点集的2D空间分布时,凸包是一个有用的工具。这个点集可以是轮廓、关键点集合等。
计算凸包,OpenCV提供了函数:
convexHull(Mat(points), hull, true);
下面的OpenCV示例程序,随机产生了一个点集,然后计算了它的凸包。并将点集和凸包画了出来。
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <fstream>
#include <iostream>
using namespace cv;
using namespace std;
static void help()
{
cout << "\nThis sample program demonstrates the use of the convexHull() function\n"
<< "Call:\n"
<< "./convexhull\n" << endl;
}
int main(int /*argc*/, char** /*argv*/)
{
Mat img(500, 500, CV_8UC3);
RNG& rng = theRNG();
help();
for (;;)
{
img = Scalar::all(0);
Mat img_filled = img.clone();
char key;
int i, count = (unsigned)rng % 100 + 1;
vector<Point> points;
for (i = 0; i < count; i++)
{
Point pt;
pt.x = rng.uniform(img.cols / 4, img.cols * 3 / 4);
pt.y = rng.uniform(img.rows / 4, img.rows * 3 / 4);
points.push_back(pt);
}
for (i = 0; i < count; i++)
circle(img, points[i], 3, Scalar(0, 0, 255), CV_FILLED, CV_AA);
//求凸包
vector<int> hull;
convexHull(Mat(points), hull, true);
//凸包顶点集
int hullcount = (int)hull.size();
vector<Point> vertices;
for (int i = 0; i < hullcount;i++)
{
vertices.push_back(points[hull[i]]);
}
//画线
Point pt0 = points[hull[hullcount - 1]];
for (i = 0; i < hullcount; i++)
{
Point pt = vertices[i];
line(img, pt0, pt, Scalar(0, 255, 0), 1, CV_AA);
pt0 = pt;
}
imshow("hull", img);
//填充
fillConvexPoly(img_filled, &vertices[0], hullcount, Scalar(255, 0, 255) , 8);
imshow("hull_filled",img_filled);
key = (char)waitKey();
if (key == 27 || key == 'q' || key == 'Q') // 'ESC'
break;
}
return 0;
}