欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MFC学习之路(11)之将多个坐标点拟合出一条直线,并画出

程序员文章站 2022-05-23 12:28:53
...

参考:https://blog.csdn.net/liyuanbhu/article/details/50866802

描述:

  • 最小二乘法直线拟合(不是常见的一元线性回归算法)
  • 将离散点拟合为 a x + b y + c = 0 型直线
  • 假设每个点的 X Y 坐标的误差都是符合 0 均值的正态分布的。
  • 与一元线性回归算法的区别:一元线性回归算法假定 X 是无误差的,只有 Y 有误差。

注:points为存入多个点的容器,利用已知点,求出直线方程中的系数a,b,c,并在onpaint()函数中画出直线

    double a, b, c;
	int size = points.size();
    if(size < 2)
     {
         a = 0;
         b = 0;
         c = 0;

     }
     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) //这时没有一个特殊的直线方向,无法拟合
         {

         }
         else
         {
             a = 1;
             b = 0;
             c = - x_mean;
         }
     }
     else
     {
         a = Dxy / den;
         b = (lambda - Dxx) / den;
         c = - a * x_mean - b * y_mean;
     }

	CDC *pDC1 = m_pic.GetWindowDC();
	CPen pen1(PS_SOLID,1,RGB(0,0,255));
	pDC1->SelectObject(&pen1);
	pDC1->MoveTo((points.at(0).x)/cx*width,-((a*points.at(0).x+c)/b)/cy*height);
	pDC1->LineTo((points.at(4).x)/cx*width,-((a*points.at(4).x+c)/b)/cy*height);

效果:
MFC学习之路(11)之将多个坐标点拟合出一条直线,并画出

参考:https://blog.csdn.net/liyuanbhu/article/details/50866802