opencv基础篇 ——(十四)轮廓拟合

32 篇文章 5 订阅

        

        轮廓拟合是指通过数学模型(如直线、圆、椭圆或多边形)来逼近或描述轮廓的形状。这一过程有助于简化复杂轮廓,提取其关键特征,或用于进一步的分析和识别。以下是轮廓拟合在OpenCV中的一些关键概念和函数:

  1. 多边形逼近(approxPolyDP

  2. 最小包围矩形(minAreaRect

  3. 最小包围圆(minEnclosingCircle

  4. 最小外接三角形(minEnclosingTriangle)
  5. 最小凸包(convexHull)
  6. 拟合直线(fitLine

  7. 椭圆拟合(FitEllipse/FitEllipseAMS/FitEllipseDirect)

        轮廓拟合在实际应用中非常广泛,比如在物体识别、形状分类、尺寸测量等方面。通过选择合适的拟合方法,可以有效地提取和利用图像中的形状信息。

多边形拟合(approxPolyDP)

        用于轮廓点集的多边形逼近的函数。它用于减少轮廓点的数量,同时保持轮廓的形状近似不变。

void cv::approxPolyDP(const InputArray curve, OutputArray approxCurve, double epsilon, bool closed)
  • 参数:

    • curveInputArray 类型,通常是一个表示轮廓点的向量,如 std::vector<cv::Point> 或 cv::Mat,包含原始轮廓上的点。
    • approxCurveOutputArray 类型,用于存储输出的逼近多边形点集,同样是一个向量或矩阵。
    • epsilondouble 类型,逼近精度参数。这是两个连续点之间的最大距离,如果两个点之间的欧几里得距离小于 epsilon,那么这两个点就可以被视为同一个点,从而进行点的合并。
    • closedbool 类型,表示输入的轮廓是否闭合。如果是闭合轮廓,通常设置为 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)
  • 参数:

    • pointsInputArray 类型,表示一组二维点的集合,通常用于表示轮廓上的点。它可以是 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)
  • 参数:

    • pointsInputArray 类型,表示一组二维点的集合,通常用于表示轮廓上的点。它可以是 cv::Mat(CV_32SC2 或 CV_32FC2 类型,即每个点包含两个元素的行向量)或者 std::vector<cv::Point>(如 std::vector<cv::Point2f> 或 std::vector<cv::Point>)。
    • centerPoint2f 类型的引用,用于存储最小圆的中心坐标。
    • radiusfloat 类型的引用,用于存储最小圆的半径。
  • 返回值: 函数返回一个布尔值,表示操作是否成功。如果成功找到最小圆,返回 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)
  • 参数:

    • pointsInputArray 类型,表示输入的点集,可以是 cv::Mat 或 std::vector<cv::Point> 类型,其中 Point 可以是 Point2f 或 Point2i,表示二维坐标点。
    • hullOutputArray 类型,用于存储计算得到的凸包点集,同样可以是 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)
  • 参数:

    • pointsInputArray 类型,表示一组点的集合,这些点构成了拟合直线的数据源。它可以是 cv::Mat 或 std::vector<cv::Point2f>(对于2D拟合)/cv::Point3f(对于3D拟合)。
    • lineOutputArray 类型,用于存储拟合得到的直线参数。对于2D拟合,它是一个 Vec4f 类型的向量,表示直线方程为 vx*x + vy*y + vz = w;对于3D拟合,它是一个 Vec6f 类型的向量,表示直线方程为 vx*x + vy*y + vz*z + vw = 0
    • distTypeint 类型,指定距离类型,用于衡量点到直线的距离。常见的选项有 cv::DIST_L2(欧氏距离)。
    • paramdouble 类型,距离函数的参数,具体意义依赖于 distType 的选择。
    • repsdouble 类型,表示拟合精度,即点到直线的最大距离与最小距离之比。
    • aepsdouble 类型,表示拟合过程中的容差,用于迭代终止条件。
  • 功能说明:

    • cv::fitLine 使用 M-estimator 技术,结合加权最小二乘法迭代拟合直线,直到满足给定的精度要求或达到迭代次数上限。
    • 该函数适用于直线拟合,但不直接支持圆、椭圆等其他形状的拟合。对于这些形状,可能需要使用其他方法或函数。
  • 应用场景:

    • 在图像处理中,可用于道路边缘检测、直线特征提取等。
    • 在三维空间分析中,可以用于三维点云数据的直线路径分析。
  • 注意事项:

    • 输入的点集应该代表了想要拟合直线的真实数据分布,噪声和异常值可能会影响拟合结果。
    • distTypeparamreps 和 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(最小二乘法) 方法计算点集的拟合椭圆
  • 参数:

    • pointsInputArray 类型,表示一组二维点的集合,通常为轮廓点。它可以是 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);

效果展示

  • 多边形拟合

  • 最小包围矩阵

  • 最小外接圆

  • 最小三角形

  • 最小凸包

  • 19
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值