参考文章
直线拟合算法(续:加权最小二乘)_加权拟合直线法-CSDN博客
对比了参考文中和opencv中的直线拟合权重,不知道理解的对不对,前者是权重平方,后者没有平方
QtWidgetsApplication1::QtWidgetsApplication1(QWidget *parent): QMainWindow(parent)
{//权重QList<qreal> _w{ 1,0.6,0.7,0.5,1 };QList<QPointF> points{ QPointF(1,3),QPointF(7,5),QPointF(10,5),QPointF(20,99),QPointF(50,200), };int size = points.size();qreal x_mean = 0;qreal y_mean = 0;qreal sum_wx = 0, sum_wy = 0, sum_w = 0;for (int i = 0; i < size; i++){qreal x = points[i].x();qreal y = points[i].y();qreal w = _w[i];sum_wx += w * w * x;sum_wy += w * w * y;sum_w += w * w;}x_mean = sum_wx / sum_w;y_mean = sum_wy / sum_w; //至此,计算出了 x y 的均值double Dxx = 0, Dxy = 0, Dyy = 0;double xy_mean1 = 0,xx_mean1 = 0, yy_mean1 = 0;double x_mean2=0, y_mean2, xy_mean2 = 0, xx_mean2 = 0, yy_mean2 = 0;qreal w_sum2=0;for (int i = 0; i < size; i++){qreal x = points[i].x();qreal y = points[i].y();qreal w = _w[i];w = w * w;Dxx += w * (x - x_mean) * (x - x_mean);Dxy += w * (x - x_mean) * (y - y_mean);Dyy += w * (y - y_mean) * (y - y_mean);xy_mean1 += w*x*y;xx_mean1 += w*x*x;yy_mean1 += w*y*y;qreal w2 = _w[i];x_mean2 += w2*x;y_mean2 += w2*y;xy_mean2 += w2*x*y;xx_mean2 += w2*x*x;yy_mean2 += w2*y*y;w_sum2 +=w2;}xy_mean1 /= sum_w;xx_mean1 /= sum_w;yy_mean1 /= sum_w;x_mean2 /= w_sum2;y_mean2 /= w_sum2;xy_mean2 /= w_sum2;xx_mean2 /= w_sum2;yy_mean2 /= w_sum2;double a, b, c;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;}else{a = 1;b = 0;c = -a * x_mean - b * y_mean;}}else{a = Dxy / den;b = (lambda - Dxx) / den;c = -a * x_mean - b * y_mean;}double dxx1 = xx_mean1 - x_mean*x_mean;double dyy1 = yy_mean1 - y_mean*y_mean;double dxy1 = xy_mean1 - x_mean*y_mean;double t1 = atan2(2*dxy1,dxx1-dyy1) / 2;double aa = sin(t1);//测试aa等于adouble bb = -cos(t1);//测试bb等于bdouble dxx2 = xx_mean2 - x_mean2*x_mean2;double dyy2 = yy_mean2 - y_mean2*y_mean2;double dxy2 = xy_mean2 - x_mean2*y_mean2;double t2= atan2(2 * dxy2, dxx2 - dyy2) / 2;double aaa = sin(t2);//测试aaa不等于aadouble bbb = -cos(t2);//测试bbb不等于bb//opencv modules/imgproc/src/linefit.cpp->fitLine2D_wods 方法下//line[0] = (float)cos(t);不等于博文中的 -b//line[1] = (float)sin(t);不等于博文中的 a//唯一的不同之处在于博文中的是权重平方,opencv中没有平方ui.setupUi(this);
}
运行结果