直线拟合算法

Posted liyuanbhu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了直线拟合算法相关的知识,希望对你有一定的参考价值。

在计算机视觉的应用中,经常会用到提取一条直线的精确位置这样的工作。这时就要用到直线的拟合算法了。

这里,我也贴一个利用最小二乘法计算最佳拟合直线的代码。

这个代码是我以前学习《机器视觉算法与应用(双语版)》[德] 斯蒂格(Steger C) 著;杨少荣 等 译 的书时写的。所有的公式推导都在书中 3.8.1 ,还算比较有用。
与一元线性回归算法的区别:一元线性回归算法假定 X 是无误差的,只有 Y 有误差。 而这个算法假设每个点的 X Y 坐标的误差都是符合 0 均值的正态分布的。 因此,在计算机视觉的应用中比普通的一元线性回归拟合的结果要好。

#include <QVector>
#include <QPoint>
#include <math.h>

/// 本代码用到了 Qt5 中的 QVector 和 QPoint。但是可以很容易的改为其他数组类型。

/**
  * 最小二乘法直线拟合(不是常见的一元线性回归算法)
  * 将离散点拟合为  a x + b y + c = 0 型直线
  * 假设每个点的 X Y 坐标的误差都是符合 0 均值的正态分布的。
  * 与一元线性回归算法的区别:一元线性回归算法假定 X 是无误差的,只有 Y 有误差。
  */
bool lineFit(const QVector<QPoint> &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) );
     a = Dxy / den;
     b = (lambda - Dxx) / den;
     c = - a * x_mean - b * y_mean;
     return true;
} 

以上是关于直线拟合算法的主要内容,如果未能解决你的问题,请参考以下文章

opencv利用hough概率变换拟合得到直线后,利用DDA算法得到直线上的像素点坐标

原创算法分享最小二乘法

关于VC的最小二乘法曲线拟合算法问题

用RANSAC算法实现干扰严重的直线拟合~

halcon之最小二乘拟合直线

PCL:多直线拟合(RANSAC)