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

时间:2015-03-30 21:25:12

标签: c# algorithm linear-algebra svd alglib

我试图将一架飞机安装到3D空间中的一组点上。我最初尝试了一个详尽的最小二乘法,但事实证明这太慢了。我读到最有效的解决方案是执行奇异值分解。

这方面的数学超出了我的要求,但我找到了一堆资源来尝试让它发挥作用。

根据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中。如果需要,我很乐意提供更多信息。

1 个答案:

答案 0 :(得分:2)

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