【问题标题】:Eigen and SVD to find Best Fitting Plane given a Set of Points给定一组点的 Eigen 和 SVD 找到最佳拟合平面
【发布时间】:2017-01-15 04:08:15
【问题描述】:

给定 3D 空间中的一组 N 个点,我正在尝试使用 SVD 和 Eigen 找到最佳拟合平面。

我的算法是:

  1. 围绕 (0,0,0) 居中数据点。
  2. 形成点坐标的 3xN 矩阵。
  3. 计算矩阵的 SVD。
  4. 将最小奇异值对应的最小奇异向量设置为平面的法线。
  5. 将原点到平面的距离设置为正常∙质心。

我不知道如何使用Eigen's SVD Module找到点坐标矩阵的最小奇异值对应的最小奇异向量。

到目前为止,我有这段代码(算法的第 1、2 和 5 步):

Eigen::Matrix<float, 3, 1> mean = points.rowwise().mean();
const Eigen::Matrix3Xf points_centered = points.colwise() - mean;

int setting = Eigen::ComputeThinU | Eigen::ComputeThinV;
Eigen::JacobiSVD<Eigen::Matrix3Xf> svd = points_centered.jacobiSvd(setting);

Eigen::Vector3d normal = **???**

double d = normal.dot(mean);

【问题讨论】:

  • 到目前为止你尝试过什么代码?
  • 在问题中添加了代码。
  • 参见presentation 的幻灯片 97-99。
  • @ggael 我想使用 SVD,我读到在某些情况下应该更精确。

标签: c++ math eigen


【解决方案1】:

表示U = svd.matrixU(),向量U.col(0)U.col(1) 定义了平面的底部,U.col(2) 与平面垂直。

U.col(0) 还定义了标准偏差最大的方向。

即使您的点是共面的,您也应该使用标志 ComputeFullU 而不是 ComputeThinU 来获得正确的尺寸。

【讨论】:

    【解决方案2】:

    您的问题基本上是如何使用 Eigen JacobiSVD 模块进行最小二乘拟合。这是一个link,其中有一个更有用的示例。最小二乘拟合的基本思想是,首先取所有N-1个点与N个点之一的向量差,然后尝试将所有这样的N-1个向量近似为两个基向量的线性组合,它定义了 2D 平面。

    【讨论】:

    • 这个链接是关于正常最小二乘拟合,而问题是关于总最小二乘
    • 我意识到我的算法不是最优的。将质心放在最佳拟合平面上更有意义,而不是 N 个点之一。我刚刚使用拉格朗日乘数从数学上推导出问题中给出的算法已经最小化了 N 个点到平面距离的平方和。这是一个与坐标无关的结论。在推导之后,算法上不再需要最小二乘了。 billx 的答案中给出了实现算法的正确代码。
    • 我的示例进行了正常的最小二乘拟合,其中使用最小二乘公式 x=(A'*A)^(-1)*A'*b 求解了超定线性方程 Ax=b。实现更加巧妙。首先对 A=USV' 执行 SVD,然后解决方案是 x=V*S^(-1)*U'*b。这避免了反转 A'*A,与 A 本身相比,它具有平方条件数。
    • 这个问题比我之前想象的更有趣。看起来最小二乘的问题最终不需要做任何最小二乘。让我来一次!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-10
    • 2016-01-11
    • 2018-04-21
    • 1970-01-01
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    相关资源
    最近更新 更多