Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 联立方程组的最小二乘解_Algorithm_Language Agnostic_Math - Fatal编程技术网

Algorithm 联立方程组的最小二乘解

Algorithm 联立方程组的最小二乘解,algorithm,language-agnostic,math,Algorithm,Language Agnostic,Math,我试图拟合从一组坐标到另一组坐标的变换 x' = R + Px + Qy y' = S - Qx + Py Where P,Q,R,S are constants, P = scale*cos(rotation). Q=scale*sin(rotation) 有一个众所周知的“手工”公式,用于将p、Q、R、S拟合到一组对应的点。 但是我需要一个拟合的误差估计,所以我需要一个最小二乘解 阅读“数字配方”,但我很难解决如何对包含x和y的数据集执行此操作 有人能举出一个例子/教程/代码示例来说明如何

我试图拟合从一组坐标到另一组坐标的变换

x' = R + Px + Qy
y' = S - Qx + Py
Where P,Q,R,S are constants, P = scale*cos(rotation). Q=scale*sin(rotation)
有一个众所周知的“手工”公式,用于将p、Q、R、S拟合到一组对应的点。 但是我需要一个拟合的误差估计,所以我需要一个最小二乘解

阅读“数字配方”,但我很难解决如何对包含x和y的数据集执行此操作

有人能举出一个例子/教程/代码示例来说明如何做到这一点吗?
不太在意语言。
但是-仅仅使用Matlab/Lapack/numpy/R的内置功能可能没有帮助

编辑:
我有一大套旧的(x,y)新的(x,y)要装。这个问题是过度确定的(数据点比未知点多),所以简单的矩阵求逆是不够的——正如我所说的,我真的需要拟合的误差。

一个问题是像这样的数字东西通常很棘手。即使算法很简单,在实际计算中也经常会出现问题


因此,如果有一个系统具有内置功能,那么最好使用它。

要找到p、Q、R和S,可以使用最小二乘法。我认为令人困惑的是,最小二乘法的通常描述使用x和y,但它们与问题中的x和y不匹配。你只需要把你的问题仔细地转化为最小二乘法框架。在你的例子中,自变量是未转换的坐标x和y,因变量是转换后的坐标x'和y',可调参数是P、Q、R和S。(如果这不够清楚,请告诉我,我会发布更多细节。)

一旦你找到了p,Q,R和S,然后scale=sqrt(p^2+Q^2),你就可以从sin-rotation=Q/scale和cos-rotation=p/scale中找到旋转。定义3x3矩阵T(p,Q,R,S),这样
(x',y',1)=T(x,y,1)
。然后计算

A = \sum_i |(T (x_i,y_i,1)) - (x'_i,y'_i,1)|^2
和最小化A对(p,Q,R,S)

自己编写此代码是一个中型到大型的项目,除非您能够保证数据具有良好的条件,特别是当您希望从过程中获得良好的错误估计时。您最好使用支持错误估计的现有最小化工具

粒子物理类型将直接使用(最容易在FoTrr77中编码),或者从(C++中的编码,或者它可以通过Python绑定访问)。但是如果你还没有这些工具中的一个的话,这是一个很大的安装


我相信其他人可以建议其他最小值。

您可以使用该程序来计算。它经过测试并集成到包括矿山在内的多种产品中。它是根据GPL授权的,但是如果这是一个非开源项目,他将为您更改许可证(收费)

下面的代码应该可以做到这一点。我对残差使用了以下公式:

residual[i] =   (computed_x[i] - actual_x[i])^2
              + (computed_y[i] - actual_y[i])^2
然后根据Wolfram的MathWorld中描述的公式推导出最小二乘公式

我在Excel中测试了这个算法,它的性能达到了预期。我使用了十个随机点的集合,然后通过随机生成的变换矩阵进行旋转、平移和缩放

在没有对输出数据施加随机噪声的情况下,该程序产生四个参数(
p
Q
R
、和
S
),这些参数与输入参数相同,且
rSquared
值为零

随着越来越多的随机噪声应用于输出点,常数开始偏离正确值,并且
rSquared
值相应增加

代码如下:

// test data
const int N = 1000;
float oldPoints_x[N] = { ... };
float oldPoints_y[N] = { ... };
float newPoints_x[N] = { ... };
float newPoints_y[N] = { ... };

// compute various sums and sums of products
// across the entire set of test data
float Ex =  Sum(oldPoints_x, N);
float Ey =  Sum(oldPoints_y, N);
float Exn = Sum(newPoints_x, N);
float Eyn = Sum(newPoints_y, N);
float Ex2 = SumProduct(oldPoints_x, oldPoints_x, N);
float Ey2 = SumProduct(oldPoints_y, oldPoints_y, N);
float Exxn = SumProduct(oldPoints_x, newPoints_x, N);
float Exyn = SumProduct(oldPoints_x, newPoints_y, N);
float Eyxn = SumProduct(oldPoints_y, newPoints_x, N);
float Eyyn = SumProduct(oldPoints_y, newPoints_y, N);

// compute the transformation constants
// using least-squares regression
float divisor = Ex*Ex + Ey*Ey - N*(Ex2 + Ey2);
float P = (Exn*Ex + Eyn*Ey - N*(Exxn + Eyyn))/divisor;
float Q = (Exn*Ey + Eyn*Ex + N*(Exyn - Eyxn))/divisor;
float R = (Exn - P*Ex - Q*Ey)/N;
float S = (Eyn - P*Ey + Q*Ex)/N;

// compute the rSquared error value
// low values represent a good fit
float rSquared = 0;
float x;
float y;
for (int i = 0; i < N; i++)
{
    x = R + P*oldPoints_x[i] + Q*oldPoints_y[i];
    y = S - Q*oldPoints_x[i] + P*oldPoints_y[i];
    rSquared += (x - newPoints_x[i])^2;
    rSquared += (y - newPoints_y[i])^2;
}
//测试数据
常数int N=1000;
浮点oldPoints_x[N]={…};
浮点数_y[N]={…};
浮点数_x[N]={…};
浮点数_y[N]={…};
//计算各种总和和乘积之和
//在整个测试数据集上
float Ex=总和(oldPoints_x,N);
float Ey=和(旧点y,N);
float Exn=总和(新点x,N);
float Eyn=总和(新点y,N);
float Ex2=总积(oldPoints_x,oldPoints_x,N);
float Ey2=总和(oldPoints_y,oldPoints_y,N);
float Exxn=SumProduct(oldPoints_x,newPoints_x,N);
float Exyn=SumProduct(oldPoints_x,newPoints_y,N);
float Eyxn=总和(旧点y,新点x,N);
float eyn=SumProduct(旧点y,新点y,N);
//计算变换常数
//使用最小二乘回归
浮点除数=Ex*Ex+Ey*Ey-N*(Ex2+Ey2);
浮点P=(Exn*Ex+Eyn*Ey-N*(Exxn+Eyyn))/除数;
浮点Q=(Exn*Ey+Eyn*Ex+N*(Exyn-Eyxn))/除数;
浮点数R=(Exn-P*Ex-Q*Ey)/N;
浮点数S=(Eyn-P*Ey+Q*Ex)/N;
//计算rSquared错误值
//低值表示适合
浮动rSquared=0;
浮动x;
浮动y;
对于(int i=0;i
谢谢你,艾哈迈斯,这几乎就是我所拥有的。我根据一本旧的陆军测量手册对其进行了编码,该手册是根据早期的“测量员须知”注释编写的,该注释必须有100年的历史!(它使用N和E表示北部和东部,而不是x/y)

“拟合优度”参数将非常有用-如果选定的点使拟合更差,我可以以交互方式抛出它们

FindTransformation(vector<Point2D> known,vector<Point2D> unknown) {
{
    // sums
    for (unsigned int ii=0;ii<known.size();ii++) {
       sum_e += unknown[ii].x;
       sum_n += unknown[ii].y;
       sum_E += known[ii].x;
       sum_N += known[ii].y;                            
       ++n;         
    }

    // mean position
    me = sum_e/(double)n;
    mn = sum_n/(double)n;
    mE = sum_E/(double)n;
    mN = sum_N/(double)n;

    // differences
    for (unsigned int ii=0;ii<known.size();ii++) {

       de = unknown[ii].x - me;
       dn = unknown[ii].y - mn;

       // for P
       sum_deE += (de*known[ii].x);
       sum_dnN += (dn*known[ii].y);
       sum_dee += (de*unknown[ii].x);
       sum_dnn += (dn*unknown[ii].y);

       // for Q
       sum_dnE += (dn*known[ii].x);
       sum_deN += (de*known[ii].y);                     
   }

double P = (sum_deE + sum_dnN) / (sum_dee + sum_dnn);
double Q = (sum_dnE - sum_deN) / (sum_dee + sum_dnn);

double R = mE - (P*me) - (Q*mn);
double S = mN + (Q*me) - (P*mn);
}
FindTransformation(向量已知,向量未知){
{
//总数

对于(unsigned int ii=0;ii您是否有一组(x_i,y_i,x''u i,y''u i)s或x+/-dx,y+/-dy…或者什么?如果x,y,x',y'中的每一个都正好有一个,那么你只能得到一个精确的解,并且没有办法提取误差估计值…最小型函数LMA/高斯-牛顿都不会给出直接误差。我想我可以计算出最佳拟合,然后从每个点计算出误差。我原以为是这样比这要简单得多(例如,一个简单的线型模式),我只是