【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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM