20.java openCV4.x 入门-Imgproc之点集拟合

专栏简介

💒个人主页
📖心灵鸡汤📖

我们唯一拥有的就是今天,唯一能把握的也是今天


建议把本文当作笔记来看,据说专栏目录里面有相应视频🤫
📰专栏目录

一、拟合直线

1.字段

列举部分,更多请查看官方文档。

DIST_L1 这是L1距离度量。它计算两点之间的绝对差值之和
DIST_L12这是加权L1距离度量。它结合了L1和L2距离的特性
DIST_L2这是欧几里得距离,也就是L2距离度量。它计算两点之间的平方差之和的平方根

2.方法说明

1.拟合给定点集的直线

fitLine(Mat points, Mat line, int distType, double param, double reps, double aeps)
参数:
points 输入的2D或3D点向量
line输出参数,表示拟合得到的直线的参数。在2D拟合的情况下,它应该是一个4个元素的向量(如Vec4f) - (vx,vy,x0,y0),其中(vx,vy)是与直线共线的归一化向量,(x0,y0)是直线上的点。在3D拟合的情况下,它应该是一个6个元素的向量(如Vec6f) - (vx,vy,vz,x0,y0,z0),其中(vx,vy,vz)是与直线共线的归一化向量,(x0,y0,z0)是直线上的点
distType 距离度量方式,用于M估计。参见DIST_*
param 可选参数,对于某些距离类型,它表示数值参数C。如果为0,则选择最优值
reps 足够精度下的半径(坐标原点到直线的距离)
aeps 对于角度的足够精度。对于reps和aeps,0.01是一个不错的默认值

拟合给定点集的直线,该函数通过最小化
∑ i ρ ( r i ) \sum_i \rho(r_i) iρ(ri)
来拟合一条直线到2D或3D点集,其中
r i 是第 i t h 个点到线和 ρ ( r ) 的距离函数 , r_i 是第 i^{th}个点到线和 \rho(r) 的距离函数, ri是第ith个点到线和ρ(r)的距离函数,
可以是以下之一:

DIST_L2
ρ ( r ) = r 2 / 2 (最简单且最快的最小二乘法方法) \rho (r) = r^2/2 \quad \text{(最简单且最快的最小二乘法方法)} ρ(r)=r2/2(最简单且最快的最小二乘法方法)
DIST_L1
ρ ( r ) = r \rho (r) = r ρ(r)=r
DIST_L12
ρ ( r ) = 2 ⋅ ( 1 + r 2 2 − 1 ) \rho (r) = 2 \cdot ( \sqrt{1 + \frac{r^2}{2}} - 1) ρ(r)=2(1+2r2 1)
DIST_FAIR
ρ ( r ) = C 2 ⋅ ( r C − log ⁡ ( 1 + r C ) ) 其中 C = 1.3998 \rho \left (r \right ) = C^2 \cdot \left ( \frac{r}{C} - \log{\left(1 + \frac{r}{C}\right)} \right ) \quad \text{其中} \quad C=1.3998 ρ(r)=C2(Crlog(1+Cr))其中C=1.3998
DIST_WELSCH
ρ ( r ) = C 2 2 ⋅ ( 1 − exp ⁡ ( − ( r C ) 2 ) ) 其中 C = 2.9846 \rho \left (r \right ) = \frac{C^2}{2} \cdot \left ( 1 - \exp{\left(-\left(\frac{r}{C}\right)^2\right)} \right ) \quad \text{其中} \quad C=2.9846 ρ(r)=2C2(1exp((Cr)2))其中C=2.9846
DIST_HUBER
ρ ( r ) = { r 2 2 if  r l t ; C C ⋅ ( r − C 2 ) 其它 其中 C = 1.345 \rho (r) = \begin{cases} \frac{r^2}{2} & \text{if } r < C \\ C \cdot (r - \frac{C}{2}) & \text{其它} \end{cases} \quad \text{其中} \quad C = 1.345 ρ(r)={2r2C(r2C)if r其它lt;C其中C=1.345
根据自身需求选择合适的距离计算类型,此处仅给出使用示例

       //创建矩阵
        Mat mat = new Mat(300,300, CvType.CV_8UC3);
        mat.setTo(new Scalar(255,255,255));

        //创建点集
        MatOfPoint points = new MatOfPoint();
        points.fromArray(new Point(30,30),
                new Point(55,30),
                new Point(110,88),
                new Point(150,200),
                new Point(100,250)
                );

        Mat line = new Mat();
        //拟合直线
        Imgproc.fitLine(points,line,Imgproc.DIST_L1,0,0.01,0.01);

        //获取拟合结果
        double vx = line.get(0, 0)[0];
        double vy = line.get(1, 0)[0];
        double x = line.get(2, 0)[0];
        double y = line.get(3, 0)[0];

        System.out.println("line.dump() = \n" + line.dump());
        //绘制点集
        for (Point point : points.toArray()) {
            Imgproc.circle(mat,point,2,new Scalar(0,0,255),-1,Imgproc.LINE_AA);
        }

        //根据拟合结果绘制直线
        Point p1 = new Point(x,y);
        Point p2 = new Point(x+200*vx,y+200*vy);
        Imgproc.line(mat,p1,p2,new Scalar(255,0,0),2);

        HighGui.imshow("mat",mat);
        HighGui.waitKey();

结果:

请添加图片描述

二、拟合椭圆

1.最佳拟合

该函数的作用是在给定的2D点集上找到一个最佳拟合的旋转椭圆,并返回表示该椭圆的 RotatedRect 对象

fitEllipse(MatOfPoint2f points)
参数:
points 一个包含2D点的 MatOfPoint2f 对象

    public static void main(String[] args) {
        // 创建一个二维点集
        MatOfPoint2f points = new MatOfPoint2f(
                new Point(100, 50),
                new Point(150, 100),
                new Point(200, 50),
                new Point(150, 0),
                new Point(100, 50)
        );

        // 调用fitEllipse方法拟合椭圆
        RotatedRect rotatedRect = Imgproc.fitEllipse(points);

        // 打印拟合的椭圆信息
        System.out.println("Center: " + rotatedRect.center);
        System.out.println("Size: " + rotatedRect.size);
        System.out.println("Angle: " + rotatedRect.angle);

    }

请自行绘制查看结果

fitEllipseDirect​(Mat points)
参数:
points 一个包含2D点的 MatOfPoint2f 对象

这里使用了由 Fitzgibbon1999 提出的直接最小二乘法(Direct)算法


    public static void main(String[] args) {
        // 假设有一组点集合,这里只是举例,实际应用中需要替换为真实数据
        Point[] pointsArray = {
                new Point(100, 50),
                new Point(150, 100),
                new Point(200, 50),
                new Point(150, 0),
                new Point(100, 50)
        };
        MatOfPoint points = new MatOfPoint(pointsArray);

        // 调用 fitEllipseAMS 方法拟合椭圆
        RotatedRect rotatedRect = Imgproc.fitEllipseDirect(points);

        // 输出椭圆的信息
        System.out.println("Center: " + rotatedRect.center);
        System.out.println("Size: " + rotatedRect.size);
        System.out.println("Angle: " + rotatedRect.angle);

        //绘制
        Mat mat = new Mat(300,300, CvType.CV_8UC3,new Scalar(255,255,255));
        List pts = new ArrayList<>();
        pts.add(points);
        Imgproc.polylines(mat,pts,true,new Scalar(255,0,0));
        Imgproc.ellipse(mat,rotatedRect,new Scalar(0,255,0));

        //显示
        HighGui.imshow("mat",mat);
        HighGui.waitKey(0);
        HighGui.destroyAllWindows();
    }


2.最小面积拟合

fitEllipseAMS根据输入的点集拟合出一个最小面积的椭圆,采用 AMS (Algebraic Method) 算法. 该函数支持更多类型的points

fitEllipse(MatOfPoint2f points)
参数:
points 输入的点坐标集合
        // 假设有一组点集合,这里只是举例,实际应用中需要替换为真实数据
        Point[] pointsArray = {
                new Point(100, 50),
                new Point(150, 100),
                new Point(200, 50),
                new Point(150, 0),
                new Point(100, 50)
        };
        MatOfPoint points = new MatOfPoint(pointsArray);

        // 调用 fitEllipseAMS 方法拟合椭圆
        RotatedRect rotatedRect = Imgproc.fitEllipseAMS(points);

        // 输出椭圆的信息
        System.out.println("Center: " + rotatedRect.center);
        System.out.println("Size: " + rotatedRect.size);
        System.out.println("Angle: " + rotatedRect.angle);

        //绘制
        Mat mat = new Mat(300,300,CvType.CV_8UC3,new Scalar(255,255,255));
        List pts = new ArrayList<>();
        pts.add(points);
        Imgproc.polylines(mat,pts,true,new Scalar(255,0,0));
        Imgproc.ellipse(mat,rotatedRect,new Scalar(0,255,0));

        //显示
        HighGui.imshow("mat",mat);
        HighGui.waitKey(0);
        HighGui.destroyAllWindows();
万水千山总是情,本栏完全公开免费。点赞+收藏30,瞬更下一篇
上一篇:Imgproc之图形绘制 下一篇:边缘检测
  • 20
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不要喷香水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值