【opencv】逼进多边形曲线

approxPolyDP 函数是 opencv中利用 来对指定的点集进行逼近,其逼近的精度是可设置的 对应的函数为:

void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed);

例如:approxPolyDP(contourMat, approxCurve, 10, true);//找出轮廓的多边形拟合曲线

第一个参数 InputArray curve:输入的点集
第二个参数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


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值