使用奇异值分解将平面拟合到一组点

Fitting a plane to a set of points using Singular Value Decomposition

我正在尝试使平面适合 3D 中的一组点 space。我最初尝试了详尽的最小二乘拟合,但结果证明太慢了。我读到最有效的解决方案是执行奇异值分解。

这方面的数学知识超出了我的范围,但我找到了很多资源来尝试让它发挥作用。

根据this post中的答案,我需要计算点的质心,将所有点减去质心,将它们放入3xN矩阵并进行SVD​​。然后我将左奇异向量作为平面的法线。

到目前为止一切顺利。

我找到了一个名为 alglib 的 C# 数学库,它具有 SVD 函数。可以找到算法的定义here。这是我遇到问题的地方,因为除了数据点矩阵之外,它还需要两个矩阵作为输入,而且我真的不明白要在其中放入什么。我 运行 这个代码不管:

Vector3 centroid = getCentroid(planeVerts);
    double[,] dataMat = substractCentroid(planeVerts, centroid);
    double[] w = new double[3];
    double[,] u = new double[1,1];
    double[,] t = new double[1, 1];

    bool a = alglib.svd.rmatrixsvd(dataMat, 3, planeVerts.Length, 0, 0, 2, ref w, ref u, ref t);

    Vector3 planeNorm = new Vector3((float) w[0], (float) w[1], (float) w[2]);

所以理论上我认为 "w" 会包含我的平面法线,但不幸的是它没有(我在 Unity3D 中可视化它并且它的角度错误)。 "u" 和 "t" 矩阵让我感到困惑,我真的不知道应该将它们设置为什么。

可以找到 rmatrixsvd 函数的详细 [​​=33=] here

有数学或算法专家运行可以分享他们在这方面的知识吗?我需要使用 C#,因为我的项目在 Unity3D 中。如果需要,我很乐意提供更多信息。

查看文档,似乎 w 将包含您的奇异值,U 将包含左奇异向量,而 V 将包含右奇异向量。由于 dataMat 是 3xN,U 应该是 3x3,V 应该是 NxN。正如你所说你需要左奇异向量,设置 UNeeded=1 并只取 U 的第一列。因为你不需要右奇异向量,你也可以设置 VNeeded=0.