轮廓拟合是指通过数学模型(如直线、圆、椭圆或多边形)来逼近或描述轮廓的形状。这一过程有助于简化复杂轮廓,提取其关键特征,或用于进一步的分析和识别。以下是轮廓拟合在OpenCV中的一些关键概念和函数:
-
多边形逼近(
approxPolyDP
) -
最小包围矩形(
minAreaRect
) -
最小包围圆(
minEnclosingCircle
) - 最小外接三角形(minEnclosingTriangle)
- 最小凸包(convexHull)
-
拟合直线(
fitLine
) -
椭圆拟合(FitEllipse/FitEllipseAMS/FitEllipseDirect)
轮廓拟合在实际应用中非常广泛,比如在物体识别、形状分类、尺寸测量等方面。通过选择合适的拟合方法,可以有效地提取和利用图像中的形状信息。
多边形拟合(approxPolyDP)
用于轮廓点集的多边形逼近的函数。它用于减少轮廓点的数量,同时保持轮廓的形状近似不变。
void cv::approxPolyDP(const InputArray curve, OutputArray approxCurve, double epsilon, bool closed)
-
参数:
curve
:InputArray
类型,通常是一个表示轮廓点的向量,如std::vector<cv::Point>
或cv::Mat
,包含原始轮廓上的点。approxCurve
:OutputArray
类型,用于存储输出的逼近多边形点集,同样是一个向量或矩阵。epsilon
:double
类型,逼近精度参数。这是两个连续点之间的最大距离,如果两个点之间的欧几里得距离小于epsilon
,那么这两个点就可以被视为同一个点,从而进行点的合并。closed
:bool
类型,表示输入的轮廓是否闭合。如果是闭合轮廓,通常设置为true
。
-
返回值: 该函数没有直接的返回值,而是将结果写入到
approxCurve
输出参数中。
功能说明:
- 逼近原理:
approxPolyDP
使用 Douglas-Peucker 算法或类似算法,这是一种递归的方法,逐步舍弃那些对轮廓形状影响较小的点,直到所有点间的距离都大于或等于epsilon
。 - 应用场景: 用于简化轮廓,减少计算量,或者在不丢失太多细节的情况下用于形状识别、特征提取等。
- 注意事项:
epsilon
参数的选择很重要,太小可能导致点数过多,太大则可能丢失轮廓细节。- 输出的多边形可能与原始轮廓有相同的起点和终点,以保持封闭性。
- 如果
closed
设置为false
,则输出的多边形可能不闭合,即使输入的轮廓是闭合的。
std::vector<cv::Point> contour;
// 假设 contour 已经填充了轮廓点
std::vector<cv::Point> approximatedContour;
cv::approxPolyDP(contour, approximatedContour, 3.0, true);
最小包围矩阵(minAreaRect)
用于计算一组二维点集(通常为轮廓点)的最小面积外接矩形。这个矩形不一定是轴对齐的,而是可以旋转的,因此它非常适合用来描述任意方向的轮廓或点集的最小边界。
RotatedRect cv::minAreaRect(InputArray points)
-
参数:
points
:InputArray
类型,表示一组二维点的集合,通常用于表示轮廓上的点。它可以是cv::Mat
(CV_32SC2 或 CV_32FC2 类型,即每个点包含两个元素的行向量)或者std::vector<cv::Point>
(如std::vector<cv::Point2f>
或std::vector<cv::Point>
)。
-
返回值: 函数返回一个
cv::RotatedRect
类型的对象,该对象描述了最小面积外接矩形。RotatedRect
包含了矩形的中心点坐标、宽度、高度以及旋转角度。旋转角度是以度为单位,范围从0度到180度,表示矩形相对于水平轴的旋转。
功能说明:
- 计算原理:
cv::minAreaRect
通过计算点集的凸包(convex hull),然后找到能够包围这些点的最小面积矩形,这个矩形可以是倾斜的。 - 应用场景: 广泛应用于图像处理和计算机视觉任务中,如文本检测、物体姿态估计、形状分析等,尤其适合于需要考虑旋转角度的轮廓或对象的边界框计算。
- 注意事项:
- 输入的点集应当是有效的,最好为轮廓的凸包,以确保计算的准确性。
- 返回的矩形宽度和高度不一定哪个更大,取决于点集的分布,但两者共同决定了矩形的最小面积。
- 若要在图像上绘制这个旋转矩形,需要使用
cv::boxPoints
函数将RotatedRect
转换为四个顶点坐标。
使用示例:
std::vector<cv::Point2f> contourPoints;
// 假设 contourPoints 已经包含了轮廓的点
cv::RotatedRect rect = cv::minAreaRect(contourPoints);
最小包围圆(minEnclosingCircle)
用于计算一个点集(通常是轮廓点)的最小面积圆。这个圆是能够完全包含所有点的最小圆,有助于在图像分析和处理中快速定位和识别对象。
bool cv::minEnclosingCircle(InputArray points, Point2f& center, float& radius)
-
参数:
points
:InputArray
类型,表示一组二维点的集合,通常用于表示轮廓上的点。它可以是cv::Mat
(CV_32SC2 或 CV_32FC2 类型,即每个点包含两个元素的行向量)或者std::vector<cv::Point>
(如std::vector<cv::Point2f>
或std::vector<cv::Point>
)。center
:Point2f
类型的引用,用于存储最小圆的中心坐标。radius
:float
类型的引用,用于存储最小圆的半径。
-
返回值: 函数返回一个布尔值,表示操作是否成功。如果成功找到最小圆,返回
true
;否则,返回false
,可能是因为输入的点集无效或为空。
功能说明:
- 计算原理:
cv::minEnclosingCircle
使用一种算法(例如迭代法)来找到能够包含所有点的最小圆心和半径。这个过程涉及多次迭代,逐渐减小圆的半径直到所有点都在圆内。 - 应用场景: 在图像处理中,最小包围圆常用于识别圆形或近似圆形的物体,或者作为形状分析的一部分。
- 注意事项:
- 输入的点集应当是有效的,且至少包含三个点,才能形成一个闭合的圆。
- 函数返回的圆心和半径是基于输入点集的坐标系的,通常这个坐标系的原点位于图像的左上角。
- 对于噪声较大的点集,最小圆的计算可能不够精确,需要根据具体应用场景考虑如何处理这种情况。
使用示例:
std::vector<cv::Point2f> contourPoints;
// 假设 contourPoints 已经包含了轮廓的点
cv::Point2f circleCenter;
float circleRadius;
if (cv::minEnclosingCircle(contourPoints, circleCenter, circleRadius)) {
// 圆心和半径已计算成功,可以进一步处理
} else {
// 计算失败,可能需要检查输入数据
}
最小外接三角形(minEnclosingTriangle)
用于找到能完全覆盖一组二维点的最小三角形。
void cv::minEnclosingTriangle ( InputArray points,
OutputArray triangle )
参数说明:
points
:输入的点集,通常是一个std::vector<cv::Point2f>
或者是一个cv::Mat
,每一行代表一个点的坐标。triangle
:输出参数,用于存储计算得到的最小面积三角形的三个顶点。
该函数会计算出一个包围给定点集的最小面积三角形,并将三角形的三个顶点存储在 triangle
中。这个函数通常用于形状分析和特征提取等任务中。
需要注意的是,minEnclosingTriangle
函数在 OpenCV 4.5.3 版本中被引入。
最小凸包(convexHull)
用于找到能完全覆盖一组二维点的最小凸包。
void cv::convexHull(InputArray points, OutputArray hull, bool clockwise=false, bool returnPoints=true)
-
参数:
points
:InputArray
类型,表示输入的点集,可以是cv::Mat
或std::vector<cv::Point>
类型,其中Point
可以是Point2f
或Point2i
,表示二维坐标点。hull
:OutputArray
类型,用于存储计算得到的凸包点集,同样可以是cv::Mat
或std::vector<cv::Point>
类型。clockwise
:布尔值,表示凸包点的顺序。如果设置为true
,则按顺时针方向排列;如果设置为false
(默认),则按逆时针方向排列。returnPoints
:布尔值,表示是否返回凸包的顶点坐标。如果设置为true
(默认),则返回顶点坐标;如果设置为false
,则返回凸包的顶点索引,而不是实际坐标。
-
功能:
cv::convexHull
使用了一种高效算法(如 Gift Wrapping 算法或 Jarvis March)来找到点集的凸包,这个凸包是一个最小的凸多边形,可以包围所有输入的点。- 函数会删除点集中多余的点,只保留构成凸包的点。
-
应用场景:
- 凸包在图像处理中广泛用于形状分析、轮廓简化、碰撞检测等。
- 在物体识别中,凸包可以作为物体的粗略表示,简化后续处理。
-
注意事项:
- 凸包不保证是最小面积的多边形,仅是最小的凸多边形。
- 如果输入点集已经排序,可以设置
clockwise
为true
来维持原有顺序,否则输出的顺序可能会变化。 - 对于非凸的点集,
convexHull
会返回一个凸包,但可能不是输入点集的最小面积多边形。
直线拟合(fitLine)
用于通过最小化误差的方式,拟合一组 2D 或 3D 点集到一条直线上。这个函数适用于多种应用场景,如直线检测、形状分析等。
void cv::fitLine(InputArray points, OutputArray line, int distType, double param, double reps, double aeps)
-
参数:
points
:InputArray
类型,表示一组点的集合,这些点构成了拟合直线的数据源。它可以是cv::Mat
或std::vector<cv::Point2f>
(对于2D拟合)/cv::Point3f
(对于3D拟合)。line
:OutputArray
类型,用于存储拟合得到的直线参数。对于2D拟合,它是一个Vec4f
类型的向量,表示直线方程为vx*x + vy*y + vz = w
;对于3D拟合,它是一个Vec6f
类型的向量,表示直线方程为vx*x + vy*y + vz*z + vw = 0
。distType
:int
类型,指定距离类型,用于衡量点到直线的距离。常见的选项有cv::DIST_L2
(欧氏距离)。param
:double
类型,距离函数的参数,具体意义依赖于distType
的选择。reps
:double
类型,表示拟合精度,即点到直线的最大距离与最小距离之比。aeps
:double
类型,表示拟合过程中的容差,用于迭代终止条件。
-
功能说明:
cv::fitLine
使用 M-estimator 技术,结合加权最小二乘法迭代拟合直线,直到满足给定的精度要求或达到迭代次数上限。- 该函数适用于直线拟合,但不直接支持圆、椭圆等其他形状的拟合。对于这些形状,可能需要使用其他方法或函数。
-
应用场景:
- 在图像处理中,可用于道路边缘检测、直线特征提取等。
- 在三维空间分析中,可以用于三维点云数据的直线路径分析。
-
注意事项:
- 输入的点集应该代表了想要拟合直线的真实数据分布,噪声和异常值可能会影响拟合结果。
distType
、param
、reps
和aeps
参数的选择对拟合结果有直接影响,需要根据具体应用调整。- 对于复杂的形状拟合需求,可能需要先进行轮廓简化或其他预处理步骤。
该函数利用最小二乘法拟合出距离所有点距离最小的直线,直线的描述形式可以转化成点斜式。函数第一个参数是待拟合直线的2D或者3D点集,可以存放在vector<>或者Mat类型的变量中赋值给参数。函数第二个参数是拟合直线的描述参数,如果是2D点集,输出量为Vec4f类型的(vx vy x0 y0),其中(vx vy)是与直线共线的归一化向量,(x0 y0)是拟合直线上的随意一点,根据这四个量可以计算得到2维平面直线的点斜式解析式,表示形式如式所示。
如果输入参数是3D点集,输出量为Vec6f类型的(vx vy vz x0 y0 z0),其中(vx vy vz)是与直线共线的归一化向量,(x0 y0 z0)是拟合直线上的随意一点。
函数第三个参数是M-estimator算法使用的距离类型标志,可以选择的距离类型在表中给出。函数第四个参数是某些距离类型中的数值参数C,如果数值0表示选择最佳值。函数第五个参数表示坐标原点与拟合直线之间的距离精度,数值0表示选择自适应参数;函数第六个参数表示拟合直线的角度精度,数值0表示选择自适应参数。第五个参数和第六个参数一般取值0.01。
椭圆拟合(FitEllipse/FitEllipseAMS/FitEllipseDirect)
此函数用于计算一个最小面积的椭圆,该椭圆能够最佳地包围或拟合给定的二维点集。这个椭圆可能不是轴对齐的,即它可以是旋转的,以更好地适应点集的分布。
RotatedRect cv::fitEllipse(InputArray points)
RotatedRect cv::fitEllipseAMS(InputArray points)
RotatedRect cv::fitEllipseDirect(InputArray points)
- fitEllipse :基于最小二乘法(least-squares sense)计算围绕一组(个数大于等于5个)给定的点集拟合一个椭圆。返回该椭圆的最小外接矩形(如果给定的点是在一条直线上,该矩形的最小边为0)。注意返回的数值可能有负数(大边界之外)。
- fitEllipseAMS:基于Approximate Mean Square(近似均方) 方法计算点集的拟合椭圆
- fitEllipseDirect:基于Direct least square(最小二乘法) 方法计算点集的拟合椭圆
-
参数:
points
:InputArray
类型,表示一组二维点的集合,通常为轮廓点。它可以是cv::Mat
(CV_32SC2 或 CV_32FC2 类型,即每个点包含两个元素的行向量)或者std::vector<cv::Point>
(如std::vector<cv::Point2f>
或std::vector<cv::Point>
)。
-
返回值: 函数返回一个
cv::RotatedRect
类型的对象,该对象描述了拟合的椭圆。RotatedRect
包含椭圆的中心点坐标、长度(相当于椭圆的主轴长度)、宽度(次轴长度)以及旋转角度。 -
应用场景:
- 在图像处理和计算机视觉中,
cv::fitEllipse
常用于识别和分析具有椭圆形状的对象,如眼睛、车轮、特定几何图形等。 - 它可以帮助提取这些对象的精确位置、大小和方向,进而用于进一步的分析或目标跟踪。
- 在图像处理和计算机视觉中,
-
注意事项:
- 输入的点集应尽量紧密地包围感兴趣的椭圆区域,以获得更准确的拟合结果。
- 拟合过程可能会受到噪声的影响,因此在应用前可能需要对点集进行适当的预处理,如滤波或轮廓简化。
- 返回的椭圆参数可以用于在图像上绘制椭圆,以可视化拟合结果。
使用示例:
std::vector<cv::Point2f> contourPoints;
// 假设 contourPoints 已经包含了轮廓的点
cv::RotatedRect ellipse = cv::fitEllipse(contourPoints);
效果展示
- 多边形拟合
- 最小包围矩阵
- 最小外接圆
- 最小三角形
- 最小凸包