【opencv】49-OpenCv深入分析轮廓

目录

1. 多边形逼近 cv::approxPolyDP()

Douglas-Peucker(dp)逼近算法

2. 几何特性概括

2.1  cv::arcLength()获得长度

2.2  cv::boundingRect()获得矩形包围框

2.3  cv::minAreaRect()获得最小矩形框

2.4  cv::minEnclosingCircle()获得最小包围圆

2.5  cv::fitEllipse()获得椭圆边框

2.6 cv::fitLine()获得轮廓的最佳拟合线

2.7  用cv::convexHull(0获得轮廓的凸包


1. 多边形逼近 cv::approxPolyDP()

当绘制一个多边形或进行形状分析时,通常需要使用多边形逼近一个轮廓,使顶点数变少。Opencv首先了其中的两种逼近方法,cv::approxPolyDP()实现的是Douglas-Peucker(dp)逼近算法。

函数原型:

void cv::approxPolyDP(
	cv::InputArray curve,
	cv::OutputArray approxCurve,
	double epsilon,
	bool closed  // if true, 
);

cv::approxPolyDP()依次处理curve输入的一个多边形。cv::approxPolyDP()的输出储存在approxCurve数组中。这些多边形既可以表示成标准模板库向量cv::Point,也可以表示为OpenCV中的大小为Nx1的cv::mat数组。curve和approxCurve应该属于同一类型。

参数epsilon是要求的逼近准确度。epsilon的含义是,允许在原多边形和最终拟合的多边形之间存在的最大偏差。

参数closed指明curve中的一系列点是否是一个闭合的多变形,若为真,认为是曲线是闭合的。

Douglas-Peucker(dp)逼近算法

该算法首先从轮廓(图B)中挑出两个最远的点,将两点相连(图C),然后在原来的轮廓上寻找一个离线段距离最远的点,将该点加入逼近后的新轮廓中。如此反复迭代,不断将最远的点添加到结果中,直到所有点到多边形的最短距离小于parameter参数指定的精度(图F)。将精度设置为轮廓的周长或外包矩形周长等表示轮廓总长度的值的几分之一比较合适。

【opencv】49-OpenCv深入分析轮廓_第1张图片

2. 几何特性概括

2.1  cv::arcLength()获得长度

函数cv::arcLength()函数用于提取输入轮廓的长度。函数声明:

double cv::arcLength(
	cv::InputArray points,  // array or vector of 2-dimensional points
	bool closed  // if true, assume link from last to first vertex
);

参数points代表轮廓,形式可以是任何常见的轮廓表示方法(如标准模板库的点向量或二通道数组)。

参数closed表示该轮廓是否是闭合的。加入轮廓是闭合的,则参数points中的最后一个点到第一个的距离也算入总弧长中。

cv::arcLength()函数中的points参数必须代表一条曲线,因此它不适用于不代表轮廓的点集

2.2  cv::boundingRect()获得矩形包围框

描述轮廓发一种最建议的方法是为它加上一个外包围框。最简单的途径是直接计算外包围矩形。函数cv::boundingRect()函数实现该功能:

cv::Rect cv::boundingRect(
	cv::InputArray points  // array or vector of 2-dimensional points
);

参数points是需要计算包围框的曲线。返回值是所需的外包围框。

cv::boundingRect()函数计算外包围框对任何点集都有用,不管这些点是否代表一条曲线

2.3  cv::minAreaRect()获得最小矩形框

cv::boundingRect()返回的cv::Rect只能表现一个四边水平和垂直的矩形。函数cv::minAreaRect()可以返回一个包围轮廓最小的矩形,这个矩形可能是倾斜的。函数声明如下:

cv::RotatedRect cv::minAreaRect(  // return rectangle bounding the points
	cv::InputArray points  // array or vector of 2-dimensional points
);

参数points可以是任何标准形式的点集,且该函数无论对曲线还是普通点集都有用。

2.4  cv::minEnclosingCircle()获得最小包围圆

函数cv::minEnclosingCircle()与矩形边界框的作用基本相同,不同的是该函数的返回值不能直接表示成现有的数据类型。所以碧玺给cv::minEnclosingCircle()函数传递所需的参考变量,函数声明:

void cv::minEnclosingCircle(
	cv::InputArray points,  // array or vector of 2-dimensional points
	cv::Point2f& center,  // result location of circle center
	float& radius,  // result radius of circle
);

输入曲线是一系列点。center和radius参数是你需要传递的,cv::minEnclosingCircle(0函数啊经返回这两个值。

cv::minEnclosingCircle()函数对曲线和其它点集都有用

2.5  cv::fitEllipse()获得椭圆边框

与最小包围圆一样,OpenCV提供函数来获得一组点集的最佳拟合椭圆边框。函数声明:

cv::RotatedRect cv::fitEllipse(  // return rect bounding ellipse (#ten-point_contour_with_the_minimal_enclo)
	cv::InputArray points  // array of vector of 2-dimensional points
);

cv::fitEllipse()函数使用拟合函数返回一个与轮廓最相似的椭圆,这意味着并不是轮廓中的所有点都会被包围在cv::fitEllipse()返回的椭圆中。该拟合由最小二乘法算出。

2.6 cv::fitLine()获得轮廓的最佳拟合线

很多情况下,轮廓是一组带噪声的对直线的采样点,这时需要解决的问题是,为观察到的点集选择一条最佳拟合线。通过最小化代价函数的方式来拟合定义如下:

cost(\overrightarrow{\Theta }) = \sum_{points:i}\rho (r_{i}), where r_{i} = r(\overrightarrow{\Theta }, \overrightarrow{x_{i} })

 \overrightarrow{\Theta }表示定义直线的参数;\overrightarrow{x_{i}}表示轮廓中的第i个点;r_{i}表示由 \overrightarrow{\Theta }表示的直线与该点之阿金的距离。从根本上说,是函数\rho (r_{i})将不同的可行拟合方法区分开。当\rho (r_{i}) = \frac{1}{2}r_{i}^{2}时,代价函数就变成了最小二乘拟合函数。在需要更稳定的拟合方法时(例如,能更恰当地处理异常数据点的拟合方法),那些更为复杂的距离函数很有用。如下展示了有效的形式以及OpenCv中相应的用于cv::fitLine()的枚举值。

distType 距离度量
cv::DIST_L2 \rho (r_{i}) = \frac{1}{2}r_{i}^{2} least-swuares方法
cv::DIST_L1 \rho (r_{i}) = r_{i}
cv::DIST_L12 \rho (r_{i}) = 2\cdot (\sqrt{1+\frac{1}{2}r^2} - 1)
cv::DIST_FAIR \rho (r_{i}) = C^2\cdot (\frac{r}{C} - log(1+\frac{r}{c})) C = 1.3998
cv::DIST_WELSCH \rho (r_{i}) = \frac{C^2}{2}\cdot (1-exp(-(\frac{r}{c})^2)) C = 2.9846
cv::DIST_HUBER \rho (r_{i}) = \left\{\begin{matrix} \frac{1}{2}r_{i}^2 & r<C \\ C\cdot (r-\frac{C}{2}) & r\geq C \end{matrix}\right. C = 1.345

cv::fitLine()函数声明如下:

void cv::fitLine(
	cv::InputArray points,  // array or vector of 2-dimensional points
	cv::OutputArray line,  // vector of Vec4f(2d), or Vec6f(3d)
	int distType,  // distance type
	double param,  // parameter for distance metric
	double reps,  // radius accuracy parameter
	double aeps  // angle accuracy parameter
);

参数points表示一组cv::Mat数组或标准模板库向量形式的点集。该函数既可以处理二维点,也可以处理三维点。

参数line应该是cv::Vec4f类型(对于二维直线)或cv::Vec6f(对于三维直线)。若是三维直线,数值中的前一半代表直线方向,后一半代表直线上的一个点。

参数distType允许我们选择所用的距离度量。distType的有效值如上表。

参数param用于为表种的一些距离度量提供参数值,该参数可以设置为0,设置为0时,函数cv::fitLine()将自动为选中的距离度量提供最优值。

参数reps和aeps代表对拟合直线的原点精度要求和角度要求,这俩参数的常用之是1e-2。

2.7  用cv::convexHull(0获得轮廓的凸包

有些情况下,我们需要i通过寻找一个多边形的凸包来简化它。

一个多边形或一条轮廓的凸包,指的是一个完全包含原轮廓且只由原轮廓上的点组成的多边形,此多边形的每一处都必须是凸的(例如,多边形上的任意连续三个点内角小于180度)。

计算凸包的用处由很多,其中特别常见的一项用处是,检测一个点是否落在以恶搞凸多边形内的发过程很快,因此在检测点是否落在一个复杂多边形内部之前,往往有必要先检测它是否落在该多边形的凸包内部。

函数cv::convecHull()计算轮廓的凸包。函数声明:

void cv::convexHull(
	cv::InputArray points, // array or vector of 2-d points
	cv::OutputArray hull,  // array of points or integer indices
	bool clockwise = false,  // true = output points will be clockwise
	bool returnPoints = true  // true = points in hull, else indices
);

参数points可以是任何形式的轮廓。

参数hull给出返回的凸包。可以设置为常规的轮廓类型结构体,cv::convecHull()会以该结构返回计算得到凸包上的点。或者提供一组整数,此时cv::convecHull()会把每一个属于凸包的点分别与一个索引对应,并在hull中返回这些索引。这样,索引将从0开始,索引值i代表点points[i]。

参数clockwise指明希望cv::convecHull()如何呈现得到的凸包。加入clockwise = true,则凸包将按顺时针方向排雷;若设为假false,将以逆时针方向排列。

参数returnPoints与参数hull中的选择有关,若参数points是一个标准模板库向量对象,则此参数会被忽略;如果points是cv::Mat类型的数组,那么需要函数返回的是点时,returnPoints必须设为true,而需要函数返回索引时,returnPoints必须设为false。

你可能感兴趣的:(openCv,opencv,计算机视觉,人工智能)