2

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

这个数学超出了我的范围,但我找到了一堆资源来尝试让它工作。

根据这篇文章的答案,我需要计算点的质心,从所有点中减去质心,将它们放入 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”和“t”矩阵让我感到困惑,我真的不知道应该将它们设置为什么。

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

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

4

1 回答 1

2

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

于 2015-03-30T21:34:11.460 回答