最小二乘法拟合空间直线的原理及实现

空间直线的表达式可以表示为:
x − b a = y − d c = z 1 \frac{x-b}{a} = \frac{y-d}{c} = \frac{z}{1} axb=cyd=1z
通过变形可得:
{ x = a × z + b y = c × z + d \begin{cases} x = a × z + b \\ y = c × z + d \end{cases} {x=a×z+by=c×z+d
用矩阵可表示为:
[ a b c d ] [ z 1 ] = [ x y ] \begin{gathered} \quad \begin{bmatrix} a & b \\ c & d \end{bmatrix} \begin{bmatrix} z \\ 1 \end{bmatrix}= \begin{bmatrix} x \\ y \end{bmatrix} \end{gathered} [acbd][z1]=[xy]
对于直线上的多个点,可表示为:
[ a b c d ] [ z 1 … z n 1 … 1 ] = [ x 1 … x n y 1 … y n ] \begin{gathered} \quad \begin{bmatrix} a & b \\ c & d \end{bmatrix} \begin{bmatrix} z_1 & \ldots &z_n \\ 1 & \ldots & 1 \end{bmatrix}= \begin{bmatrix} x_1 & \ldots & x_n \\ y_1 & \ldots &y_n \end{bmatrix} \end{gathered} [acbd][z11zn1]=[x1y1xnyn]
等号两边的矩阵右边同时乘以:
[ z 1 1 … … z n 1 ] \begin{gathered} \quad \begin{bmatrix} z_1 & 1 \\ \ldots & \ldots \\z_n & 1 \end{bmatrix} \end{gathered} z1zn11
则有:
[ a b c d ] [ ∑ i = 1 n z i 2 ∑ i = 1 n z i ∑ i = 1 n z i n ] = [ ∑ i = 1 n x i z i ∑ i = 1 n x i ∑ i = 1 n y i z i ∑ i = 1 n y i ] \begin{gathered} \quad \begin{bmatrix} a & b \\ c & d \end{bmatrix} \begin{bmatrix} \sum_{i=1}^n z_i^2 & \sum_{i=1}^n z_i \\ \sum_{i=1}^n z_i & n \end{bmatrix}= \begin{bmatrix} \sum_{i=1}^n x_i z_i & \sum_{i=1}^n x_i \\ \sum_{i=1}^n y_i z_i & \sum_{i=1}^n y_i \end{bmatrix} \end{gathered} [acbd][i=1nzi2i=1nzii=1nzin]=[i=1nxizii=1nyizii=1nxii=1nyi]
最后可得:
[ a b c d ] = [ ∑ i = 1 n x i z i ∑ i = 1 n x i ∑ i = 1 n y i z i ∑ i = 1 n y i ] [ ∑ i = 1 n z i 2 ∑ i = 1 n z i ∑ i = 1 n z i n ] − 1 \begin{gathered} \quad \begin{bmatrix} a & b \\ c & d \end{bmatrix}= \begin{bmatrix} \sum_{i=1}^n x_i z_i & \sum_{i=1}^n x_i \\ \sum_{i=1}^n y_i z_i & \sum_{i=1}^n y_i \end{bmatrix} \begin{bmatrix} \sum_{i=1}^n z_i^2 & \sum_{i=1}^n z_i \\ \sum_{i=1}^n z_i & n \end{bmatrix}^{-1} \end{gathered} [acbd]=[i=1nxizii=1nyizii=1nxii=1nyi][i=1nzi2i=1nzii=1nzin]1

C++程序为:

#include<iostream>
#include<math.h>

/*
设空间直线方程为:
x-b   y-d    z
--- = --- = ---
 a     c     1
 
a = e[0][0]
b = e[0][1]
c = e[1][0]
d = e[1][1]

*/ 

using namespace std;
void matrix_inverse(double(*a)[2], double(*b)[2]);

int main()
{
	int i, j, M, N;
	double f[][3] = {
						{0,1,2},
						{1,2,3},
						{2,3,4},
						{3,4,5},
						{4,5,6},
						{5,6,7},
						{6,7,8},
						{7,8,9},
						{8,9,10}
					};
	M = sizeof(f) / sizeof(f[0]);
	
	double a[M][3] = { 0 };
	for (i = 0; i < M; i++)
	{
		for(j = 0; j < 3; j++)
			a[i][j] = f[i][j];
	}
	
	double b[2][2] = { 0 };
	double c[2][2] = { 0 };
	double d[2][2] = { 0 };
	double e[2][2] = { 0 };
	
	for ( i = 0; i < M; i++ )
	{
		b[0][0] = b[0][0] + ( a[i][0] * a[i][2] );
		b[0][1] = b[0][1] + a[i][0];
		b[1][0] = b[1][0] + ( a[i][1] * a[i][2] );
		b[1][1] = b[1][1] + a[i][1];
	}
	
	for ( i = 0; i < M; i++ )
	{
		c[0][0] = c[0][0] + pow( a[i][2] , 2 );
		c[0][1] = c[0][1] + a[i][2];
		c[1][0] = c[1][0] + a[i][2];
		c[1][1] = M;
	}
	
	matrix_inverse(c, d);  //求逆函数
	
	e[0][0] = (b[0][0] * d[0][0]) + (b[0][1] * d[1][0]);	// a
	e[0][1] = (b[0][0] * d[0][1]) + (b[0][1] * d[1][1]);	// b
	e[1][0] = (b[1][0] * d[0][0]) + (b[1][1] * d[1][0]);	// c
	e[1][1] = (b[1][0] * d[0][1]) + (b[1][1] * d[1][1]);	// d
	
//	for (i = 0; i < 2; i++)	//显示系数 
//	{
//		for (j = 0; j < 2; j++)
//			cout << " " << e[i][j] << "\t";
//		cout << "\n";
//	}
	return 0;
 }
 
 void matrix_inverse(double(*a)[2], double(*b)[2])
{
	using namespace std;
	int i, j, k;
	double max, temp;
	// 定义一个临时矩阵t
	double t[2][2];
	// 将a矩阵临时存放在矩阵t[n][n]中
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
			t[i][j] = a[i][j];
	// 初始化B矩阵为单位矩阵
	for (i = 0; i < 2; i++)
		for (j = 0; j < 2; j++)
			b[i][j] = (i == j) ? (double)1 : 0;
	// 进行列主消元,找到每一列的主元
	for (i = 0; i < 2; i++)
	{
		max = t[i][i];
		// 用于记录每一列中的第几个元素为主元
		k = i;
		// 寻找每一列中的主元元素
		for (j = i + 1; j < 2; j++)
		{
			if (fabs(t[j][i]) > fabs(max))
			{
				max = t[j][i];
				k = j;
			}
		}
		//cout<<"the max number is "<<max<<endl;
		// 如果主元所在的行不是第i行,则进行行交换
		if (k != i)
		{
			// 进行行交换
			for (j = 0; j < 2; j++)
			{
				temp = t[i][j];
				t[i][j] = t[k][j];
				t[k][j] = temp;
				// 伴随矩阵B也要进行行交换
				temp = b[i][j];
				b[i][j] = b[k][j];
				b[k][j] = temp;
			}
		}
		if (t[i][i] == 0)
		{
			cout << "\nthe matrix does not exist inverse matrix\n";
			break;
		}
		// 获取列主元素
		temp = t[i][i];
		// 将主元所在的行进行单位化处理
		//cout<<"\nthe temp is "<<temp<<endl;
		for (j = 0; j < 2; j++)
		{
			t[i][j] = t[i][j] / temp;
			b[i][j] = b[i][j] / temp;
		}
		for (j = 0; j < 2; j++)
		{
			if (j != i)
			{
				temp = t[j][i];
				//消去该列的其他元素
				for (k = 0; k < 2; k++)
				{
					t[j][k] = t[j][k] - temp * t[i][k];
					b[j][k] = b[j][k] - temp * b[i][k];
				}
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值