Línea recta Opencv-Fit

concepto

El método de mínimos cuadrados fue propuesto por AM Legendre en su libro "Un nuevo método para calcular las órbitas de los cometas" en 1805. El método de mínimos cuadrados consiste en hacer que el objeto de ajuste esté infinitamente cerca del objeto de destino minimizando la suma de cuadrados del error. En el procesamiento de imágenes, se utiliza principalmente para ajustar la línea. Al encontrar la línea con el menor error de distancia del punto de muestreo, puede ser una línea recta, una curva, una elipse, un círculo, etc. Los métodos de resolución se dividen actualmente en estimación de polinomios y probabilidad (máxima verosimilitud).

  1. El ajuste de polinomios del método de mínimos cuadrados, de acuerdo con un punto dado, encuentra su función y = f (x).
    Suponiendo que I = 1,2,3, ... n, encuentre la curva aproximada y = φ (x) y minimice la suma de las desviaciones cuadradas de y = φ (x) e y = f (x).
  2. El método de estimación de máxima verosimilitud es formar una función de distribución de probabilidad P combinando el valor verdadero y el error del valor medido, y luego L (x) después de la combinación, y obteniendo la derivada parcial de x para obtener una función de distribución normal.
    Inserte la descripción de la imagen aquí

teoría

Resumen de mínimos cuadrados

programa

Utilice opencv para lograr:

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

Más adelante se añadirán ejemplos de círculos adecuados.

Artículo de referencia:
¿Cómo entender el método de mínimos cuadrados?

Supongo que te gusta

Origin blog.csdn.net/baidu_35536188/article/details/112599885
Recomendado
Clasificación