python - 如何在 Open3d 中对齐/注册两个网格? (Python)

标签 python registration mesh open3d trimesh

我有两个 .ply 文件,其中包含形状相似的对象网格。它们最初是不对齐的。我想实现两个网格对象的全局注册。有没有一种方法可以做到这一点,而无需首先导入点云数据,进行全局配准,然后重新构建网格?

我已经尝试了 open3d 文档 ( http://www.open3d.org/docs/0.12.0/tutorial/pipelines/global_registration.html ) 中列出的步骤,它对于点云效果很好。然而,从点云重建网格是具有挑战性的,因为它们是相对复杂的形状,所以我想避免这种情况。

提前谢谢您!

最佳答案

主要思想是您不需要从点云重建网格。

将您拥有的数据标记为mesh_amesh_bpcl_apcl_b

  1. 如果您的 pcl_a/b 是直接从 mesh_a/bpcl_a/bmesh_a/b 中提取的 具有相同的变换矩阵,您可以简单地将点云对齐获得的变换矩阵应用于网格。

  2. 如果您的点云数据与网格数据没有关系。您可以先将mesh_a/b采样到点云并进行配准,或者直接从网格数据中获取网格顶点作为点云。其余工作与案例一相同。

以下是情况二的示例。

import copy

import numpy as np
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.706, 0])
    target_temp.paint_uniform_color([0, 0.651, 0.929])
    source_temp.transform(transformation)
    o3d.visualization.draw_geometries([source_temp, target_temp])


def preprocess_point_cloud(pcd, voxel_size):
    print(":: Downsample with a voxel size %.3f." % voxel_size)
    pcd_down = pcd.voxel_down_sample(voxel_size)

    radius_normal = voxel_size * 2
    print(":: Estimate normal with search radius %.3f." % radius_normal)
    pcd_down.estimate_normals(
        o3d.geometry.KDTreeSearchParamHybrid(radius=radius_normal, max_nn=30))

    radius_feature = voxel_size * 5
    print(":: Compute FPFH feature with search radius %.3f." % radius_feature)
    pcd_fpfh = o3d.pipelines.registration.compute_fpfh_feature(
        pcd_down,
        o3d.geometry.KDTreeSearchParamHybrid(radius=radius_feature, max_nn=100))
    return pcd_down, pcd_fpfh


def execute_global_registration(source_down, target_down, source_fpfh,
                                target_fpfh, voxel_size):
    distance_threshold = voxel_size * 1.5
    print(":: RANSAC registration on downsampled point clouds.")
    print("   Since the downsampling voxel size is %.3f," % voxel_size)
    print("   we use a liberal distance threshold %.3f." % distance_threshold)
    result = o3d.pipelines.registration.registration_ransac_based_on_feature_matching(
        source_down, target_down, source_fpfh, target_fpfh, True,
        distance_threshold,
        o3d.pipelines.registration.TransformationEstimationPointToPoint(False),
        3, [
            o3d.pipelines.registration.CorrespondenceCheckerBasedOnEdgeLength(
                0.9),
            o3d.pipelines.registration.CorrespondenceCheckerBasedOnDistance(
                distance_threshold)
        ], o3d.pipelines.registration.RANSACConvergenceCriteria(100000, 0.999))
    return result


def main():
    voxel_size = 0.01
    print(":: Load two mesh.")
    target_mesh = o3d.io.read_triangle_mesh('bunny.ply')
    source_mesh = copy.deepcopy(target_mesh)
    source_mesh.rotate(source_mesh.get_rotation_matrix_from_xyz((np.pi / 4, 0, np.pi / 4)), center=(0, 0, 0))
    source_mesh.translate((0, 0.05, 0))
    draw_registration_result(target_mesh, source_mesh, np.identity(4))

    print(":: Sample mesh to point cloud")
    target = target_mesh.sample_points_uniformly(1000)
    source = source_mesh.sample_points_uniformly(1000)
    draw_registration_result(source, target, np.identity(4))

    source_down, source_fpfh = preprocess_point_cloud(source, voxel_size)
    target_down, target_fpfh = preprocess_point_cloud(target, voxel_size)
    result_ransac = execute_global_registration(source_down, target_down,
                                                source_fpfh, target_fpfh,
                                                voxel_size)
    print(result_ransac)
    draw_registration_result(source_down, target_down, result_ransac.transformation)
    draw_registration_result(source_mesh, target_mesh, result_ransac.transformation)


if __name__ == '__main__':
    main()

enter image description here enter image description here enter image description here enter image description here

关于python - 如何在 Open3d 中对齐/注册两个网格? (Python),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70160183/

相关文章:

python - 如何在 python 的 selenium webdriver 中禁用 chrome 通知弹出窗口

Python 使用 *args 键入 Callable,同时强制执行第一个参数

javascript - Ruby on Rails 多个 collection_select

printing - 3D 打印固有的不可定向表面

python - Scrapy 正在重定向直接链接

python - 带有单引号、双引号或三引号的 Lex 字符串

php - 在 symfony 中使用 PrePersist

django - 为什么在安装了 "auth_user does not exist"应用程序的新创建的 django 项目上运行 "migrate"时会出现 "registration redux"错误?

c++ - 多个网格或单个网格中的多个对象?

3d - 计算两个网格之间的 Hausdorff 距离