直线拟合算法(续)

来源:互联网 发布:mac 找不到原始项目 编辑:程序博客网 时间:2024/05/16 07:50

直线拟合算法(续)

以前写过一篇博客,介绍直线拟合算法。

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 说明xiyi是线性无关的。再往下还可以细分为 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;}
1 0
原创粉丝点击