加权最小二乘法 - 拟合三维点集的平面

5
我正在使用最小二乘法将平面拟合到一个三维点集上。我已经有实现该算法的方法,但我想修改它以使用加权最小二乘法。这意味着每个点都有一个权重(权重越大,平面就应该越接近该点)。
当前的算法(未加权)如下所示:
计算总和:
for(Point3D p3d : pointCloud) {
    pos = p3d.getPosition();
    fSumX += pos[0];
    fSumY += pos[1];
    fSumZ += pos[2];
    fSumXX += pos[0]*pos[0];
    fSumXY += pos[0]*pos[1];
    fSumXZ += pos[0]*pos[2];
    fSumYY += pos[1]*pos[1];
    fSumYZ += pos[1]*pos[2];
}

然后制作矩阵:
double[][] A = {
    {fSumXX, fSumXY, fSumX},
    {fSumXY, fSumYY, fSumY},
    {fSumX,  fSumY,  pointCloud.size()}
};

double[][] B =  {
    {fSumXZ},
    {fSumYZ},
    {fSumZ}
};

那么,如何使用权重来修改此内容呢?谢谢!

解决 Ax = B 并且解的三个分量是拟合平面的系数...。因此,请问能否帮我如何修改以使用权重?谢谢!


4
如果你的分数很高(比如>20),或者坐标有很大的偏移量,请不要按照你目前的方式计算统计数据(通过对原始位置平方求和)--这种方法对数字误差的灵敏度很差。至少,你可以先减去X/Y/Z坐标的平均值,然后进行处理,在最后加上偏移量。还有其他特定于算法的方法,但我不太清楚你的算法如何使用最小二乘法,所以无法提供更多帮助。 - Jason S
什么是偏移量?(抱歉,在这个上下文中不理解它) - Jaa-c
3
示例:点 p1=(10001, 10002, 10003)、p2=(10005, 10006, 10007) 和 p3=(10009, 10004, 10008) 的平均值为 (10005, 10004, 10006)。因此,您需要通过相反的平移量来偏移(平移)点坐标,以获得 p1' = (-4, -2, -3)、p2' = (0, 2, 1) 和 p3' = (4, 0, 2)。然后进行您的数学计算,最后再加回平移量。 - Jason S
3个回答

9

直觉

平面上由法向量n和平面上的一点p定义的点x遵守:n.(x - p) = 0。如果一个点y不在平面上,n.(y - p)将不等于零,因此定义成|n.(y - p)|^2是一种有用的成本方式。这是点y到平面的平方距离。

在权重相等的情况下,您想找到最小化总平方误差的n,并对点求和:

f(n) = sum_i | n.(x_i - p) |^2

现在假设我们知道平面上的某个点p。我们可以轻松地计算出其中一个点作为质心,它只是点云中点的分量平均值,将始终位于最小二乘平面中。
解决方案
让我们定义一个矩阵M,其中每一行都是第i个点x_i减去质心c,我们可以重写为:
f(n) = | M n |^2

你应该能够说服自己,这个矩阵乘法版本与前一个方程中的求和是相同的。
然后,您可以对M进行奇异值分解,所需的n由与最小奇异值对应的M的右奇异向量给出。
要加入权重,只需为每个点定义一个权重w_i。计算c作为点的加权平均值,并将sum_i | n.(x_i - c) |^2更改为sum_i | w_i * n.(x_i - c) |^2,以及类似地更改矩阵M。然后像之前一样解决问题。

3

将每个和式中的每一项都乘以相应的权重。例如:

fSumZ += weight * pos[2];
fSumXX += weight * pos[0]*pos[0];

由于pointCloud.size()是所有点的数量之和,应该用所有权重的总和来替换它。


我认为将每个术语乘以权重应该足够了,但我不确定... 我会尝试并回来的。谢谢。 - Jaa-c

1

从重新定义最小二乘误差计算开始。该公式试图将误差平方和最小化。将平方误差乘以两点距离减少的函数。然后尝试最小化加权平方误差和从中导出系数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接