概念
最小二乘法是勒讓德( A. M. Legendre)于1805年在其著作《計算慧星軌道的新方法》中提出的。 最小二乘法就是通過最小化誤差的平方和,使得擬合對象無限接近目標對象。在圖像處理中主要用于擬合線,通過求采樣點距離誤差最小的線,可以是直線,曲線,橢圓,圓等。求解方法目前分為多項式和概率(最大似然)估計兩種。
- 最小二乘法多項式擬合,根據給定的點,求出它的函數y=f(x)。
假設有點 , I = 1,2,3,……n,求近似曲線y=φ(x),并且使得y=φ(x)與y=f(x)的平方偏差和最小。 - 最大似然估計方法是通過將真實值和測量值得誤差形成一個概率分布函數P,聯立后L(x),求x的偏導,得到一個正態分布函數。
理論
最小二乘法小結
程序
使用opencv實現下:
int main()
{vector<Point> points;points.push_back(Point(25, 40));points.push_back(Point(7, 6));points.push_back(Point(11, 10));points.push_back(Point(12, 14));points.push_back(Point(35, 69));points.push_back(Point(30, 50));points.push_back(Point(43, 57));points.push_back(Point(25, 37));points.push_back(Point(27, 39));points.push_back(Point(50, 100));Mat src = Mat::zeros(200, 200, CV_8UC3);for (int i = 0; i < points.size(); i++){circle(src, points[i], 3, Scalar(0, 0, 255), 1, 8);}int N = 2;Mat A = Mat::zeros(N, N, CV_64FC1);for (int row = 0; row < A.rows; row++){for (int col = 0; col < A.cols; col++){for (int k = 0; k < points.size(); k++){A.at<double>(row, col) = A.at<double>(row, col) + pow(points[k].x, row + col);}}}//構建B矩陣Mat B = Mat::zeros(N, 1, CV_64FC1);for (int row = 0; row < B.rows; row++){for (int k = 0; k < points.size(); k++){B.at<double>(row, 0) = B.at<double>(row, 0) + pow(points[k].x, row) * points[k].y;}}Mat X;solve(A, B, X, DECOMP_LU);cout << X << endl;vector<Point>lines;for (int x = 0; x < src.size().width; x++){ // y = b + ax;double y = X.at<double>(0, 0) + X.at<double>(1, 0) * x;printf("(%d,%lf)\n", x, y);lines.push_back(Point(x, y));}polylines(src, lines, false, Scalar(255, 0, 0), 1, 8);imshow("擬合線", src);waitKey(0);return 0;
}
后面會再增加擬合圓的例子
參考文章:
如何理解最小二乘法?