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

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

最佳答案

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

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

相关文章:

c - 如何设计金盒游戏的策略和算法

python-3.x - 遍历图表中的所有可用路径

performance - 矩阵求逆的最快方法

c# - 向 SQL Server Full Text Stemmer 添加单词

c# - 用于复杂方法调用的 PInvoke C#

algorithm - 确定 Int 是否为 Haskell 中的完美正方形的方法是什么?

python - 为什么 Gauss-Jacobi 方法的特定 numpy 实现会显着减少迭代次数?

c# - log4net:将标题写入每个滚动日志段

c# - 如何在 EF6 中使用临时表

c++ - Eigen 线性代数求解器似乎很慢