Halcon、OpenCV、C++ 实现最小二乘法拟合直线


最小二乘法拟合直线

概念:最小二乘法多项式直线拟合,根据给定的点,求出它的函数y=f(x),当然求得准确的函数是不太可能的,但是我们能求出它的近似曲线y=φ(x)

原理
假设有点  , I = 1,2,3,……n,求近似曲线y=φ(x),并且使得y=φ(x)与y=f(x)的平方偏差和最小,偏差

  

 

其中我们要找到一组最好的a b ,“最好的”就是要使选出的a b能使得所有的误差达到最小化。

在此要注意以下,y=ax+b 这里面的未知量是什么,很自然的说法是x y,实际上并不是,我们不用去解这个x和y ,因为x和y已经是给定的值了,当我们在找这条直线的时候,我们实际上并不关心x的值有多好,我们要的就是a 和b这两个变量,它们可以描述x和y之间的关系,我们就是在试图找出那条最适合的直线所对应的a和b。

可以看到最小二乘法对各个变量求偏导,使得偏导值为0,即可得到最小值,因为e是关于a b的函数,导数为0的点必定是最小值,进入正题

 分别对 a b求偏导可以得到:


Halcon最小二乘法拟合直线

 1 首先随机生成一组数据  2 
 3 Mx:=[100:10:500]  4 
 5 tuple_length(Mx,len)  6 
 7 tuple_gen_const(len,5,r)  8 
 9 Ma:=2
10 
11 Mb:=40
12 
13 tuple_rand(len , noise) 14 
15 My:= Ma *Mx + Mb*noise 16 
17 gen_circle(ContCircle, My, Mx, r)


 

 1 接下来用矩阵进行最小二乘求解  2 
 3 * y = ax + b  4 
 5 * y1 = ax1 + b  6 
 7 * y2 = ax2 + b  8 
 9 * ... ....... 10 
11 * yn = ax + b

 

 1 create_matrix(len,1,My,y)  2 
 3 create_matrix(len,2,1,x)  4 
 5 set_value_matrix(x, [0:len-1], gen_tuple_const(len, 0),Mx)  6 
 7 
 8 * XT 代表X的转置 inv(*)代表*的逆  9 
10 * x beta = y 11 
12 * xT x beta = xT y 13 
14 * beta = inv( xT x) xT y 15 
16 mult_matrix(x,x,'ATB',xtx) 17 
18 mult_matrix(x,y,'ATB',xty) 19 
20 invert_matrix(xtx,'general', 0, invxtx) 21 
22 mult_matrix(invxtx,xty,'AB', beta) 23 
24 get_full_matrix(beta, Values) 25 
26 Newy:=Values[0] * [10,800] + Values[1] 27 
28 gen_contour_polygon_xld(Contour, Newy, [10,800])

OpenCV最小二乘法拟合直线

 1 #include<iostream>
 2 #include<opencv2\opencv.hpp>
 3 using namespace std;  4 using namespace cv;  5  
 6  
 7 int main()  8 {  9     vector<Point>points; 10     //(27 39) (8 5) (8 9) (16 22) (44 71) (35 44) (43 57) (19 24) (27 39) (37 52)
11  
12     points.push_back(Point(27, 39)); 13     points.push_back(Point(8, 5)); 14     points.push_back(Point(8, 9)); 15     points.push_back(Point(16, 22)); 16     points.push_back(Point(44, 71)); 17     points.push_back(Point(35, 44)); 18     points.push_back(Point(43, 57)); 19     points.push_back(Point(19, 24)); 20     points.push_back(Point(27, 39)); 21     points.push_back(Point(37, 52)); 22     Mat src = Mat::zeros(400, 400, CV_8UC3); 23  
24     for (int i = 0;i < points.size();i++) 25  { 26         //在原图上画出点
27         circle(src, points[i], 3, Scalar(0, 0, 255), 1, 8); 28  } 29     //构建A矩阵 
30     int N = 2; 31     Mat A = Mat::zeros(N, N, CV_64FC1); 32  
33     for (int row = 0;row < A.rows;row++) 34  { 35         for (int col = 0; col < A.cols;col++) 36  { 37             for (int k = 0;k < points.size();k++) 38  { 39                 A.at<double>(row, col) = A.at<double>(row, col) + pow(points[k].x, row + col); 40  } 41  } 42  } 43     //构建B矩阵
44     Mat B = Mat::zeros(N, 1, CV_64FC1); 45     for (int row = 0;row < B.rows;row++) 46  { 47  
48         for (int k = 0;k < points.size();k++) 49  { 50             B.at<double>(row, 0) = B.at<double>(row, 0) + pow(points[k].x, row)*points[k].y; 51  } 52  } 53     //A*X=B
54  Mat X; 55     //cout << A << endl << B << endl;
56  solve(A, B, X,DECOMP_LU); 57     cout << X << endl; 58     vector<Point>lines; 59     for (int x = 0;x < src.size().width;x++) 60     {                // y = b + ax;
61         double y = X.at<double>(0, 0) + X.at<double>(1, 0)*x; 62         printf("(%d,%lf)\n", x, y); 63  lines.push_back(Point(x, y)); 64  } 65     polylines(src, lines, false, Scalar(255, 0, 0), 1, 8); 66     imshow("src", src); 67     
68     //imshow("src", A);
69     waitKey(0); 70     return 0; 71 }

C++最小二乘法拟合直线

 1 #include  2 #include  3 #include  4  
 5 using namespace std;  6  
 7 int main(int argc, char *argv[])  8 {  9   int num = 0; 10  
11   cout << " Input how many numbers you want to calculate:"; 12   cin >> num; 13  
14   valarray data_x(num); 15   valarray data_y(num); 16  
17   while( num ) 18   { 19     cout << "Input the "<< num <<" of x:"; 20     cin >> data_x[num-1]; 21     cout << "Input the "<< num <<" of y:"; 22     cin >> data_y[num-1]; 23     num--; 24   } 25  
26 double A =0.0; 27 double B =0.0; 28 double C =0.0; 29 double D =0.0; 30  
31 A = (data_x*data_x).sum(); 32 B = data_x.sum(); 33 C = (data_x*data_y).sum(); 34 D = data_y.sum(); 35  
36 double k,b,tmp =0; 37 if(tmp=(A*data_x.size()-B*B)) 38 { 39   k = (C*data_x.size()-B*D)/tmp; 40   b = (A*D-C*B)/tmp; 41 } 42  
43 else
44 { 45   k=1; 46   b=0; 47 } 48  
49 cout <<"k="< cout <<"b="<</p>
50  
51 return 0; 52 }

 


免责声明!

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



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM