Opencv-Fit straight line

concept

The method of least squares was proposed by AM Legendre in his book "A New Method for Calculating Comet Orbits" in 1805. The least square method is to make the fitting object infinitely close to the target object by minimizing the sum of squares of the error. In image processing, it is mainly used to fit the line. By finding the line with the smallest distance error of the sampling point, it can be a straight line, a curve, an ellipse, a circle, etc. Solving methods are currently divided into polynomial and probability (maximum likelihood) estimation.

  1. The least squares method polynomial fitting, according to a given point, find its function y=f(x).
    Assuming that I = 1,2,3,...n, find the approximate curve y=φ(x), and minimize the sum of square deviations of y=φ(x) and y=f(x).
  2. The maximum likelihood estimation method is to obtain a normal distribution function by forming a probability distribution function P by combining the true value and the error of the measured value, and after L(x), find the partial derivative of x.
    Insert picture description here

theory

Summary of Least Squares

program

Use opencv to achieve:

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;
}

Examples of fitting circles will be added later

Reference article:
How to understand the least squares method?

Guess you like

Origin blog.csdn.net/baidu_35536188/article/details/112599885