直線擬合算法


在計算機視覺的應用中,經常會用到提取一條直線的精確位置這樣的工作。這時就要用到直線的擬合算法了。

這里,我也貼一個利用最小二乘法計算最佳擬合直線的代碼。

這個代碼是我以前學習《機器視覺算法與應用(雙語版)》[德] 斯蒂格(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;
}

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com