OpenCV2馬拉松第25圈——直線擬合與RANSAC算法


計算機視覺討論群162501053


收入囊中
  • 最小二乘法(least square)擬合
  • Total least square 擬合
  • RANSAC擬合

葵花寶典

關於least square擬合,我在http://blog.csdn.net/abcd1992719g/article/details/25424061有介紹,或者看以下


終於,我們就能解出B


可是。這樣的least square有問題,比方針對垂直線段就不行。於是引入另外一種total least square



我們能夠計算得到N,解出(a,b),然后得到d.


可是誤差點對least square的影響非常大。例如以下




於是,提出了RANSAC算法
  1. 隨機在數據集中選出小的子集(對於直線,一般選2)
  2. 計算得到符合這個子集合的最好模型
  3. 找到接近符合這個模型的數據集
  4. 迭代一定次數,選出最好的模型
有圖有真相



或者參考 這里

RANSAC用在直線擬合上。就是

Repeat times:

    •Drawpoints uniformly at random
    •Fit line to theses points
    •Find inliers to this line among the remaining points(i.e., points whose distance from the line is less thant)
    •If there ared or more inliers, accept the line and refit using all inliers(refit的意思就是:我們迭代后找到了一條最好直線,如果有200個接近點。那么就用這200個點再進行least square又一次擬合下)


RANSAC是一個概率算法,迭代次數越多越准確

Pros
簡單通用
能夠解決非常多問題
實踐有效
Cons
須要確定一系列參數
有時候須要迭代次數多。概率算法有時候會失敗
最小樣本數無法得到有效模型


初識API

OpenCV提供了一個擬合直線的方法。能夠擬合2維和3維空間的直線
C++:  void  fitLine (InputArray  points, OutputArray  line, int  distType, double  param, double  reps, double  aeps )
 
  • points – 2D或者3D點的輸入向量。存儲在std::vector<> 或者 Mat中.
  • line –2D來說 (就像Vec4f) - (vx, vy, x0, y0),(vx, vy)是歸一化直線方向,(x0, y0)是直線上的一個點. 對於3D的擬合 (就如 Vec6f) - (vx, vy, vz, x0, y0, z0),
  • distType – 例如以下
  • param – 一般取0
  • reps – 一般取0.01
  • aeps – 一般取0.01

The function fitLine fits a line to a 2D or 3D point set by minimizing \sum_i \rho(r_i) where r_i is a distance between the i^{th} point, the line and \rho(r) is a distance function, one of the following:

  • distType=CV_DIST_L2

    \rho (r) = r^2/2  \quad \text{(the simplest and the fastest least-squares method)}

  • distType=CV_DIST_L1

    \rho (r) = r

  • distType=CV_DIST_L12

    \rho (r) = 2  \cdot ( \sqrt{1 + \frac{r^2}{2}} - 1)

  • distType=CV_DIST_FAIR

    \rho \left (r \right ) = C^2  \cdot \left (  \frac{r}{C} -  \log{\left(1 + \frac{r}{C}\right)} \right )  \quad \text{where} \quad C=1.3998

  • distType=CV_DIST_WELSCH

    \rho \left (r \right ) =  \frac{C^2}{2} \cdot \left ( 1 -  \exp{\left(-\left(\frac{r}{C}\right)^2\right)} \right )  \quad \text{where} \quad C=2.9846

  • distType=CV_DIST_HUBER

    \rho (r) =  \fork{r^2/2}{if $r < C$}{C \cdot (r-C/2)}{otherwise} \quad \text{where} \quad C=1.345




荷槍實彈


cv::Vec4f line;
cv::fitLine(cv::Mat(points),line,CV_DIST_L2, 0, 0.01,0.01);
這樣調用,就能夠得到我們的直線參數


舉一反三

 cv::fitEllipse 在一系列2D點中擬合橢圓. 它返回一個旋轉過的矩形 (一個cv::RotatedRect實例),橢圓內切於這個矩形. 你能夠書寫例如以下代碼:

cv::RotatedRect rrect= cv::fitEllipse(cv::Mat(points));
cv::ellipse(image,rrect,cv::Scalar(0));

函數cv::ellipse用來畫出你得到的橢圓




免責聲明!

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



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