void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed);
例如:approxPolyDP(contourMat, approxCurve, 10, true);//找出轮廓的多边形拟合曲线
第二个参数OutputArray approxCurve:输出的点集,当前点集是能最小包容指定点集的。画出来即是一个多边形;
第三个参数double epsilon:指定的精度,也即是原始曲线与近似曲线之间的最大距离。
第四个参数bool closed:若为true,则说明近似曲线是闭合的,反之,若为false,则断开。
该函数采用是道格拉斯-普克算法(Douglas-Peucker)算法来实现。该算法也以Douglas-Peucker算法和迭代终点拟合算法为名。算法的目的是给出由线段组成的曲线(在某些上下文中也称为折线),以找到具有较少点的相似曲线。 该算法基于原始曲线和简化曲线(即曲线之间的豪斯多夫距离)之间的最大距离定义“不相似”。 简化曲线由定义原始曲线的点的子集组成。
算法描述如下:
起始曲线是有序的一组点或线,距离维度ε> 0。该算法递归地划分线。 最初给出了第一点和最后一点之间的所有点。 它会自动标记要保存的第一个和最后一个点。 然后找到距离第一点和最后一点组成的线段的最远的点作为终点; 这一点在距离终点之间的近似线段的曲线上显然最远。 如果该点比线段更接近于ε,那么当前未被标记的任何点将被保存,而没有简化的曲线比ε更差的可以丢弃。
如果离线段最远的点距离近似值大于ε,则必须保留该点。 该算法以第一个点和最远点递归地调用自身,然后以最远点和最后一个点(包括最远点被标记为保留)递归调用自身。
当递归完成时,可以生成一个新的输出曲线,其中包括所有且仅标记为保留的点。
非参数Ramer-Douglas-Peucker
ε的选择通常是用户定义的。 像大多数线拟合/多边形近似/主点检测方法一样,通过使用由于数字化/量化的误差界限作为终止条件,可以使其非参数化
代码如下:
#include<opencv2\opencv.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main()
{
Mat image(600, 600, CV_8UC3, Scalar::all(255));
//imshow("image", image);
RNG &rng = theRNG();
while (1)
{
char key;
int count = (unsigned)rng % 100; //产生随机数的个数不大于10
cout << "cout为:" << count << endl;
vector<Point>points; //vector容器存放Point坐标
for (int i = 0; i < count; i++)
{
Point point;
point.x = rng.uniform(image.cols / 4, image.rows * 3 / 4);
point.y = rng.uniform(image.cols / 4, image.rows * 3 / 4);
points.push_back(point); //在vector尾部加入一个点向量
cout << "vector容器中存放的个点坐标" << point << endl;
}
cout << "基于Mat类的vector" << Mat(points) << endl; //以矩阵的形式存储
cout << points.size() << endl; //产生随机点的个数
image = Scalar::all(0); //Scale::all(0)表示所以点设为0,即全部为黑色的窗口等价于下面
//Mat image(600, 600, CV_8UC3, Scalar::all(255));
/**********************根据给定的随机点集,寻找最小包围盒*******************************/
Point2f center;
float radius = 0;
minEnclosingCircle(Mat(points), center, radius); //求出最小包围圆的圆心与半径
/*********************************绘制随机点的颜色****************/
for (int i = 0; i < count; i++)
{
circle(image, points[i], 3,
Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)),//用随机数产生随机颜色
2, 8, 0);
}
/************************绘制多边形逼进曲线**********************************/
vector<Point>approCurve;
Mat srcImge_approCurve(600, 600, CV_8UC3, Scalar::all(255));
approxPolyDP(points, approCurve, 5, true);
cout << "approCurve" << approCurve << endl;
cout << approCurve.size() << endl;
for (int i = 0; i < approCurve.size() - 1; i++)
{
line(image, approCurve[i], approCurve[i + 1], Scalar(0, 255, 255), 2, 8);
}
line(image, approCurve[approCurve.size() - 1], approCurve[0], Scalar(255, 255, 0), 2, 8);
imshow("多边形逼进", image);
key = (char)waitKey();
if (key == 27 || key == 'q' || key == 'Q')
{
break;
}
}
return 0;
}
参考:http://blog.csdn.net/wangmengmeng99/article/details/72500712