【问题标题】:Computing the 3D Transformation between Two Sets of Points计算两组点之间的 3D 变换
【发布时间】:2013-12-11 19:20:08
【问题描述】:

使用 Microsoft Kinect,我正在收集有关对象的深度数据。从这些数据中,我创建了一个点“云”(点云),当绘制它时,我可以查看我使用 Kinect 扫描的对象。

但是,我希望能够从不同的“视图”收集多个点云并将它们对齐。更具体地说,我想使用诸如Iterative Closest Point (ICP) 之类的算法来执行此操作,通过计算我收集的每个云与之前收集的云之间的旋转和平移来转换我的点云中的每个点。

但是,虽然我了解 ICP 背后的过程,但我不明白如何在 3D 中实现它。也许是我缺乏数学经验,或者是我对 OpenCV 等框架缺乏经验,但我找不到解决方案。我想避免像点云库这样为我做这种事情的库,因为我想自己做。

感谢任何和所有建议(如果有我可以研究的涉及 OpenCV/python 的解决方案,那就更好了!)

【问题讨论】:

    标签: python opencv computer-vision


    【解决方案1】:

    我自己目前正在与 ICP 作斗争。以下是我目前收集到的内容:

    ICP包括三个步骤:

    • 给定两个点云 A 和 B,找到 A 和 B 之间可能表示空间中相同点的点对。这通常通过将每个点与另一个云中最近的相邻点进行匹配来完成,但您可以使用颜色、纹理或表面法线等其他特征来改进匹配。然后,您可以选择丢弃最差的匹配项。
    • 给定这个对应对列表,找到从 A 到 B 的最佳转换
    • 将此变换应用于 A 中的所有点
    • 重复这三个步骤,直到找到可接受的解决方案。

    第一步很简单,虽然有很多方法可以优化它的速度,因为这是ICP的主要性能瓶颈;并提高准确性,因为这是错误的主要来源。 OpenCV 可以通过FLANN library 为您提供帮助。

    我认为您的麻烦在于第二步,即在给定对应列表的情况下找到最佳转换。

    一种常见的方法适用于Singular Value Decomposition (SVD)。这是算法的粗略草图。搜索ICP & SVD会得到很多进一步的参考。

    • 取对应点A1..An和B1..Bn的列表从第 1 步开始
    • 计算A中所有点的质心Ca和B中所有点的质心Cb
    • 计算 3x3 协方差矩阵 M
      M = (A1 - Ca)* (B1 - Cb)T + ... + (An - Ca)* (Bn - Cb )T
    • 使用 SVD 计算 M 的 3x3 矩阵 U 和 V
      (OpenCV 有一个 function to perform SVD
    • 计算 R = U * VT
      这是您想要的最佳旋转矩阵。
    • 将最优平移计算为 Cb - R*Ca
    • 最佳转换是 R 和此平移的组合

    请注意,我自己还没有实现这个算法,所以我只是解释我读到的内容。

    【讨论】:

    • 感谢您与我分享您的发现 - 也许我可以尽快实施此方法并通知您结果
    • 我确实会尝试在假期后将这种方法实施到我的项目中。衷心感谢您的洞察力。
    • 注意应该是R = V * U^T
    • 您应该对找到的对应关系执行一些异常值过滤以提高收敛性。例如。 trimmed-ICP 中的方法适用于部分重叠的点云。 libpointmatcher 是一个相当不错的开源 c++ 实现,也许您可​​以查看源代码,了解一些想法
    【解决方案2】:

    可以在 Rusinkievicz 的旧论文here 中找到关于 ICP 的非常好的介绍,包括加速变体。

    【讨论】:

      【解决方案3】:

      一种新的 ICP 算法现在在 OpenCV contrib(表面匹配模块)中。它还受益于各种类型的变体(包括 Rusinkievicz 等):

      http://docs.opencv.org/3.0-beta/modules/surface_matching/doc/surface_matching.html

      对于 MATLAB 实现: http://www.mathworks.co.jp/matlabcentral/fileexchange/47152-icp-registration-using-efficient-variants-and-multi-resolution-scheme/content/icp_mod_point_plane_pyr.m

      【讨论】:

      • 我试过你的 ICP 方法的 matlab 实现。我有几个问题: 1- 源点和映射点的点数是否有限制?点数应该相同吗? 2-我注意到该算法需要点云的网格。当点的数量不是很多并且集群具有凹特征时,这将成为一个挑战。对于具有凹面特征的点云,您会推荐哪种网格生成器?
      • 1.从本质上讲,不期望点数相等。 2. 预计没有网格。这是不必要的。
      • 我的空间用完了,所以我不得不在下面继续我们的对话。
      • 第一个链接(opencv的)坏了
      【解决方案4】:

      @tdirdal:

      好的,那么我可能没有查看正确的代码。 我说的是这个包link: 代码首先构造一个变换矩阵,然后加载一个包含网格(面和顶点)的 *.ply。其余代码取决于已加载的网格。

      我有一个非常简单的问题,如果您能告诉我如何使用 ICP 方法解决这个问题,我将不胜感激。我有以下两个点云。 P2 是 P39 的子集,我想在 P39 中找到 P2。请告诉我如何使用你的 matlab 包来解决这个问题。

      P2:

      11.2706 -5.3392 1.1903

      13.6194 -4.8500 2.6222

      8.8809 -3.8407 1.1903

      10.7704 -2.1800 2.6222

      8.5570 -1.0346 1.1903

      13.1808 -2.5632 1.1903

      P39:

      -1.9977 -4.1434 -1.6750

      -4.3982 -3.5743 -3.1069

      -6.8065 -3.0071 -1.6751

      -9.2169 -2.4386 -3.1070

      -11.6285 -1.8696 -1.6751

      -16.4505 -0.7305 -1.6751

      -14.0401 -1.3001 -3.1070

      -18.8577 -0.1608 -3.1070

      -25.9398 -0.8647 -3.1070

      -30.1972 -4.6857 -3.1069

      -28.2349 -2.5200 -3.1069

      -29.5843 -0.2496 -1.6751

      -31.1688 -2.0974 -3.1070

      -21.2580 0.4093 -1.6751

      -23.6450 0.9838 -3.1070

      -26.0636 1.5073 -1.6751

      -28.4357 1.9258 -3.1070

      【讨论】:

      • Ply 不一定是网格。它很可能是一个点云。因此,如果您有网格,只需使用加载网格的顶点。否则,只加载顶点。
      • 对于这个简单的问题,你可以做一些ransac方案来找到最好的对齐方式(只是抽样一些随机集并尝试注册,如果你不能得到一个合理的,你应该很倒霉1000 次迭代)。但是,对于真实的场景,请看一下我描述的表面匹配模块。这正好解决了这个问题。
      • 好吧,你有一个根本性的错误。 ICP 仅在点云通过一些粗略对齐初始化时才有效。这意味着,它们在某种意义上应该重叠。 ICP只是像优化一样的梯度下降。您应该在提供的链接中阅读有关它的更多信息。
      猜你喜欢
      • 2015-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-08
      • 2019-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多