zoukankan      html  css  js  c++  java
  • 【OpenCV3】直线拟合--FitLine()函数详解

    一、FitLine()函数原型

    CV_EXPORTS_W void fitLine( 
      InputArray points,    // 待输入点集(一般为二维数组或vector点集)
      OutputArray line,     // 输出点集(一个是方向向量,另一个是拟合直线上的点)(Vec4f(2d)或Vec6f(3d)的vector)
      int distType,         // 距离类型
      double param,         // 距离参数
      double reps,       // 径向的精度参数
      double aeps );       // 角度精度参数 

    第一个参数是用于拟合直线的输入点集,可以是二维点的cv::Mat数组,也可以是二维点的STL vector。

    第二个参数是输出的直线,对于二维直线而言类型为cv::Vec4f,对于三维直线类型则是cv::Vec6f,输出参数的前半部分给出的是直线的方向,而后半部分给出的是直线上的一点(即通常所说的点斜式直线)。

    第三个参数是距离类型,拟合直线时,要使输入点到拟合直线的距离和最小化(即下面公式中的cost最小化),可供选的距离类型如下表所示,ri表示的是输入的点到直线的距离。

    CV_DIST_USER =-1, /* User defined distance */
    CV_DIST_L1 =1, /* distance = |x1-x2| + |y1-y2| */
    CV_DIST_L2 =2, /* the simple euclidean distance */
    CV_DIST_C =3, /* distance = max(|x1-x2|,|y1-y2|) */
    CV_DIST_L12 =4, /* L1-L2 metric: distance = 2(sqrt(1+x*x/2) - 1)) */
    CV_DIST_FAIR =5, /* distance = c^2(|x|/c-log(1+|x|/c)), c = 1.3998 */
    CV_DIST_WELSCH =6, /* distance = c^2/2(1-exp(-(x/c)^2)), c = 2.9846 */
    CV_DIST_HUBER =7 /* distance = |x|<c ? x^2/2 : c(|x|-c/2), c=1.345 */

    第四个参数是距离参数,跟所选的距离类型有关,值可以设置为0,cv::fitLine()函数本身会自动选择最优化的值

    第五、六两个参数用于表示拟合直线所需要的径向和角度精度,通常情况下两个值均被设定为1e-2。

    下面,从一个具体的例子来看cv::Line()实际拟合的效果。

    #include <opencv2/opencv.cpp>
    #include <vector>
    #include <iostream>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
            //创建一个用于绘制图像的空白图
        cv::Mat image = cv::Mat::zeros(480, 640, CV_8UC3);
     
        //输入拟合点
        std::vector<cv::Point> points;
        points.push_back(cv::Point(48, 58));
        points.push_back(cv::Point(105, 98));
        points.push_back(cv::Point(155, 160));
        points.push_back(cv::Point(212, 220));
        points.push_back(cv::Point(248, 260));
        points.push_back(cv::Point(320, 300));
        points.push_back(cv::Point(350, 360));
        points.push_back(cv::Point(412, 400));
     
        //将拟合点绘制到空白图上
        for (int i = 0; i < points.size(); i++)
        {
            cv::circle(image, points[i], 5, cv::Scalar(0, 0, 255), 2, 8, 0);
        }
     
        cv::Vec4f line_para; 
        cv::fitLine(points, line_para, cv::DIST_L2, 0, 1e-2, 1e-2);
     
        std::cout << "line_para = " << line_para << std::endl;
     
        //获取点斜式的点和斜率
        cv::Point point0;
        point0.x = line_para[2];
        point0.y = line_para[3];
     
        double k = line_para[1] / line_para[0];
     
        //计算直线的端点(y = k(x - x0) + y0)
        cv::Point point1, point2;
        point1.x = 0;
        point1.y = k * (0 - point0.x) + point0.y;
        point2.x = 640;
        point2.y = k * (640 - point0.x) + point0.y;
     
        cv::line(image, point1, point2, cv::Scalar(0, 255, 0), 2, 8, 0);
     
        cv::imshow("image", image);
        cv::waitKey(0);
    
        return 0;
    }

    参考链接:(1)https://blog.csdn.net/guduruyu/article/details/69505487

         (2)https://blog.csdn.net/qq_29540745/article/details/72779847

  • 相关阅读:
    [算法] 堆栈
    [刷题] PTA 02-线性结构3 Reversing Linked List
    java IO流 (八) RandomAccessFile的使用
    java IO流 (七) 对象流的使用
    java IO流 (六) 其它的流的使用
    java IO流 (五) 转换流的使用 以及编码集
    java IO流 (四) 缓冲流的使用
    java IO流 (三) 节点流(或文件流)
    java IO流 (二) IO流概述
    java IO流 (一) File类的使用
  • 原文地址:https://www.cnblogs.com/hs-pingfan/p/10477937.html
Copyright © 2011-2022 走看看