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



我正在尝试将一个平面拟合到三维空间中的一组点。我最初尝试了一个详尽的最小二乘法拟合,但结果太慢了。我读到最有效的解决方案是执行奇异值分解。

这方面的数学计算我无法理解,但我已经找到了很多资源来尝试实现这一点。

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

到目前为止还不错。

我发现了一个名为alglib的C#数学库,它有一个SVD函数。算法的定义可以在这里找到。这就是我遇到的问题,因为除了数据点矩阵之外,还需要另外两个矩阵作为输入,我真的不知道该在它们里面放什么。我运行了这个代码不管:

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"one_answers"t"矩阵让我感到困惑,我真的不知道应该把它们设置为什么

rmatrixsvd函数的详细API可以在这里找到。

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

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

最新更新