直線擬合算法(續)


直線擬合算法(續)

曾經寫過一篇博客。介紹直線擬合算法。

http://blog.csdn.net/liyuanbhu/article/details/50866802

給出的代碼事實上有一點小問題,就是 den = 0 時會出現除以 0 的錯誤。

今天正好也有網友問起這個問題。

我就再寫一篇短文來說說怎樣解決問題。

首先我們知道:

den=D2xy+(λDxx)2

那么 den=0 意味着:

Dxy=0λ=Dxx

我們還有關於 λ 的計算式:

λ=Dxx+Dyy(DxxDyy)2+4D2xy2

帶入后得到:

DyyDxx=|DyyDxx|

也就是要求 DyyDxx

有了這些就能夠分析分析了。

Dxy=0 說明 xi yi 是線性無關的。再往下還能夠細分為 2 種情況。

  1. Dyy>Dxx 這時數據點落在一條垂直直線上,直線方程為 x=x¯
  2. Dyy=Dxx 數據均勻分布,找不到特殊的方向,無法擬合直線方程。

依照這個分析。我們能夠改進我們的代碼:

bool lineFit(const std::vector<cv::Point> &points, double &a, double &b, double &c)
{
     int size = points.size();
     if(size < 2)
     {
         a = 0;
         b = 0;
         c = 0;
         return false;
     }
     double x_mean = 0;
     double y_mean = 0;

     for(int i = 0; i < size; i++)
     {
         x_mean += points[i].x;
         y_mean += points[i].y;
     }
     x_mean /= size;
     y_mean /= size; //至此。計算出了 x y 的均值

     double Dxx = 0, Dxy = 0, Dyy = 0;

     for(int i = 0; i < size; i++)
     {
         Dxx += (points[i].x - x_mean) * (points[i].x - x_mean);
         Dxy += (points[i].x - x_mean) * (points[i].y - y_mean);
         Dyy += (points[i].y - y_mean) * (points[i].y - y_mean);
     }

     double lambda = ( (Dxx + Dyy) - sqrt( (Dxx - Dyy) * (Dxx - Dyy) + 4 * Dxy * Dxy) ) / 2.0;
     double den = sqrt( Dxy * Dxy + (lambda - Dxx) * (lambda - Dxx) );

     if(fabs(den) < 1e-5)
     {
         if( fabs(Dxx / Dyy - 1) < 1e-5) //這時沒有一個特殊的直線方向,無法擬合
         {
             return false;
         }
         else
         {
             a = 1;
             b = 0;
             c = - x_mean;
         }
     }
     else
     {
         a = Dxy / den;
         b = (lambda - Dxx) / den;
         c = - a * x_mean - b * y_mean;
     }
     return true;
}


免責聲明!

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



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