我正在尝试将一个平面拟合到三维空间中的一组点。我最初尝试了一个详尽的最小二乘法拟合,但结果发现这太慢了。我听说最有效的解决方案是执行奇异值分解。
这方面的数学我做不到,但我已经找到了一堆资源来试着让它工作。
根据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函数的详细api可以找到here
有没有数学或算法方面的老手可以分享他们在这方面的知识?我需要使用C,因为我的项目在Unity3D中。如果需要,我很乐意提供更多信息。

最佳答案

看一下文档,看起来w将包含您的奇异值,U将包含左奇异向量,V将包含右奇异向量因为dataMat是3xN,所以U应该是3x3,V应该是NxN正如你所说,你需要左奇异向量,设置uneeded=1,取u的第一列,因为你不需要右奇异向量,你也可以设置vneeded=0。

关于c# - 使用奇异值分解将平面拟合到一组点,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29356594/

10-10 02:57