python - Open3D 向 ICP 注册显示错误为 0 并返回输入转换

标签 python registration point-clouds open3d

我尝试使用 open3d 的 ICP 算法来找到一种变换,使 2 个点云之间的距离最小化,并大致遵循他们的教程页面:http://www.open3d.org/docs/latest/tutorial/pipelines/icp_registration.html (我使用Ubuntu 20.04)

我尝试使用我的 ouster128 中的点云,但它不起作用,因此我决定使用我用 numpy 创建的 2 个“虚拟”点云。 icp 注册方法获取一个转换作为输入,在我的例子中,总是返回输入转换(它基本上什么也不做,可能是因为错误为 0)。这是代码(复制粘贴后应该可以使用):

import numpy as np
import copy
import open3d as o3d

def draw_registration_result(source, target, transformation):
    source_temp = copy.deepcopy(source)
    target_temp = copy.deepcopy(target)
    source_temp.paint_uniform_color([1, 0.206, 0])
    target_temp.paint_uniform_color([0, 0.651, 0.929])
    print("Transformation: " + str(transformation))
    source_temp.transform(transformation)
    coord_frame = o3d.geometry.TriangleMesh.create_coordinate_frame()
    o3d.visualization.draw_geometries([source_temp, target_temp, coord_frame],
                                  zoom=0.5,
                                  front=[0.9288, -0.2951, -0.2242],
                                  lookat=[0, 1, 1],
                                  up=[0, 0, 1])


src_points = np.array([
    [0.0, 0.0, 0.0],
    [1.0, 0.0, 0.0],
    [2.0, 0.0, 0.0],
    [0.0, 1.0, 0.0],
    [1.0, 1.0, 0.0],
    [2.0, 1.0, 0.0],
    [0.0, 2.0, 0.0],
    [1.0, 2.0, 0.0],
    [2.0, 2.0, 0.0],
    [0.0, 3.0, 0.0],
    [1.0, 3.0, 0.0],
    [2.0, 3.0, 0.0],
])
tgt_points = np.array([
    [0.0, 0.0, 0.1], # Due to the 0.1 the clouds do not match perfectly
    [1.0, 0.0, 0.1],
    [2.0, 0.0, 0.1],
    [0.0, 1.0, 0.1],
    [1.0, 1.0, 0.1],
    [2.0, 1.0, 0.1],
    [0.0, 2.0, 0.1],
    [1.0, 2.0, 0.1],
    [2.0, 2.0, 0.1],
    [0.0, 3.0, 0.1],
    [1.0, 3.0, 0.1],
    [2.0, 3.0, 0.1],
]) 
o3d.utility.set_verbosity_level(o3d.utility.VerbosityLevel.Debug)
source = o3d.geometry.PointCloud()
source.points = o3d.utility.Vector3dVector(src_points)

target = o3d.geometry.PointCloud()
target.points = o3d.utility.Vector3dVector(tgt_points)

trans_init = np.asarray([[1.0, 0.0, 0.0, 0.0],
                         [0.0, 1.0, 0.0, 0.0],
                         [0.0, 0.0, 1.0, 0.0],
                         [0.0, 0.0, 0.0, 1.0]])

threshold = 0.02
reg_p2p = o3d.pipelines.registration.registration_icp(
    source, target, threshold, trans_init,
    o3d.pipelines.registration.TransformationEstimationPointToPoint())
print("Post Registration")
print("Inlier Fitness: ", reg_p2p.fitness)
print("Inlier RMSE: ", reg_p2p.inlier_rmse)
draw_registration_result(source, target, reg_p2p.transformation)

目标是相同的点云。唯一的区别是,target 在 z 方向上平移了 0.1。初始变换是单位矩阵。我期望的输出矩阵与 I 相同,只是 I[2][4]=0.1。现在,fitnessinlier_rmse 为 0。这没有任何意义(除非我完全误解了某些内容),因为这意味着云完全匹配,但它们显然不匹配做。有时适应度不为零(例如,当sourcetarget是相同的云时,除了target的3个点平移0.1 )。

在发布此帖子之前我尝试过的操作:

  1. 2 个不同版本的 open3d(0.15.2 和 0.16.0)。
  2. 不同的点云
  3. 不同的初始转换
  4. 一些阈值,2e-10、2e-6、0.2

(可视化窗口为白色,必须旋转相机才能查看云) 那么,我在这里做错了什么?提前致谢。

最佳答案

好的,最后我解决了。 在这种情况下,我会责怪文档,因为它说: “max_correspondence_distance (float) – 最大对应点对距离。” 在他们的教程中,这个参数称为“阈值”,我希望算法一直运行,直到误差小于阈值。但是,如果误差大于阈值,算法不会启动。这应该在文档中更准确地表述。尤其是在教程中,这个问题必须得到解决。如果我使用阈值 50,它会按预期工作。

关于python - Open3D 向 ICP 注册显示错误为 0 并返回输入转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74878923/

相关文章:

c++ - 轴对齐边界框的点云库旋转

python - 几何 - 将 3D 点划分为具有特定角度的线段

python - 使用 BS4 从列表中获取值

django - 易于使用的 django 验证码或带有验证码的注册应用程序?

javascript - 防止假注册的最佳方法是什么?

point-cloud-library - 如何使用 PCL 提取点云数据中的一组点?

Python - list.remove 在列表上迭代时

python - 编译成字节码占用太多内存

python - Doubley 在 Python 3 中解压一个可迭代对象会删除可迭代对象吗?

javascript - Google Recaptcha Ajax 响应奇怪的检查顺序