基于Open3D的点云处理16-特征点匹配

这篇具有很好参考价值的文章主要介绍了基于Open3D的点云处理16-特征点匹配。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

点云配准

将点云数据统一到一个世界坐标系的过程称之为点云配准或者点云拼接。(registration/align)

点云配准的过程其实就是找到同名点对;即找到在点云中处在真实世界同一位置的点。

常见的点云配准算法:
ICP、Color ICP、Trimed-ICP 算法流程:

  1. 选点:
    确定参与到配准过程中的点集。
  2. 匹配确定同名点对:
    ICP以两片点云中欧式空间距离最小的点对为同名点
  3. 非线性优化求解:
    采用SVD或者四元数求解变换
  4. 变换:
    将求解的变换参数应用到待配准点云上
  5. 迭代:
    计算此时的状态参数判断配准是否完成。以前后两次参数迭代变
    化的差或者RMSE值是否小于给定阈值为迭代终止条件。否则返回(1)

ICP 算法以两片点云中欧式空间距离最小的点对为同名点,如果初始点选择不合适,可能会陷入局部最优配准失败。

基于点特征的配准方法
两种方式:
一种通过特征描述,先分割出场景里的点线等特征,利用这些点进行同名点的匹配,如基于几何空间一致性筛选同名点对。
一种通过点特征描述符确定同名点,如基于FPFH双向最近邻确定同名点对,FPFH描述向量最大的特性是对于点云的同名点的特征向量表现出相似性,即该点云的同名点之间的FPFH特征描述子的二范数趋于零。

测试用例

基于icp的点云匹配(参考)

  • 点到点的配准
import open3d as o3d
import numpy as np

# 获取示例数据
source_cloud = o3d.io.read_point_cloud("./data/cloud_bin_0.pcd")
target_cloud = o3d.io.read_point_cloud("./data/cloud_bin_1.pcd")
source_cloud.paint_uniform_color([1, 0.706, 0])
target_cloud.paint_uniform_color([0, 0.651, 0.929])
threshold = 0.02# RMSE残差阈值,小于该残差阈值,迭代终止

#初始位姿
trans_init = np.asarray([[0.862, 0.011, -0.507, 0.5],
                         [-0.139, 0.967, -0.215, 0.7],
                         [0.487, 0.255, 0.835, -1.4], [0.0, 0.0, 0.0, 1.0]])
                         
# 显示未配准点云
o3d.visualization.draw_geometries([source_cloud, target_cloud],
                                  zoom=0.4459,
                                  front=[0.9288, -0.2951, -0.2242],
                                  lookat=[1.6784, 2.0612, 1.4451],
                                  up=[-0.3402, -0.9189, -0.1996])


# 点到点的ICP
result = o3d.pipelines.registration.registration_icp(
        source_cloud, target_cloud, threshold,trans_init,
        o3d.pipelines.registration.TransformationEstimationPointToPoint())
print(result)
print("Transformation is:")
print(result.transformation)

# 显示点到点的配准结果
source_cloud.transform(result.transformation)
o3d.visualization.draw_geometries([source_cloud, target_cloud],
                                  zoom=0.4459,
                                  front=[0.9288, -0.2951, -0.2242],
                                  lookat=[1.6784, 2.0612, 1.4451],
                                  up=[-0.3402, -0.9189, -0.1996])


配准前:
基于Open3D的点云处理16-特征点匹配,三维数据处理,Open3d,算法,python
配准结果:
基于Open3D的点云处理16-特征点匹配,三维数据处理,Open3d,算法,python
基于Open3D的点云处理16-特征点匹配,三维数据处理,Open3d,算法,python

  • 点到面的配准
import open3d as o3d
import numpy as np

# 获取示例数据
source_cloud = o3d.io.read_point_cloud("./data/cloud_bin_0.pcd")
target_cloud = o3d.io.read_point_cloud("./data/cloud_bin_1.pcd")
source_cloud.paint_uniform_color([1, 0.706, 0])
target_cloud.paint_uniform_color([0, 0.651, 0.929])
threshold = 0.02# RMSE残差阈值,小于该残差阈值,迭代终止

#初始位姿
trans_init = np.asarray([[0.862, 0.011, -0.507, 0.5],
                         [-0.139, 0.967, -0.215, 0.7],
                         [0.487, 0.255, 0.835, -1.4], [0.0, 0.0, 0.0, 1.0]])
                         

source_cloud = o3d.io.read_point_cloud("./data/cloud_bin_0.pcd")
target_cloud = o3d.io.read_point_cloud("./data/cloud_bin_1.pcd")
source_cloud.paint_uniform_color([1, 0.706, 0])
target_cloud.paint_uniform_color([0, 0.651, 0.929])

# 显示未配准点云
o3d.visualization.draw_geometries([source_cloud, target_cloud],
                                  zoom=0.4459,
                                  front=[0.9288, -0.2951, -0.2242],
                                  lookat=[1.6784, 2.0612, 1.4451],
                                  up=[-0.3402, -0.9189, -0.1996])

# 点到面的ICP
result = o3d.pipelines.registration.registration_icp(
    source_cloud, target_cloud, threshold,trans_init,
    o3d.pipelines.registration.TransformationEstimationPointToPlane())
print(result)
print("Transformation is:")
print(result.transformation, "\n")

# 显示点到面的配准结果
source_cloud.transform(result.transformation)
o3d.visualization.draw_geometries([source_cloud, target_cloud],
                                  zoom=0.4459,
                                  front=[0.9288, -0.2951, -0.2242],
                                  lookat=[1.6784, 2.0612, 1.4451],
                                  up=[-0.3402, -0.9189, -0.1996])


配准结果如图:
基于Open3D的点云处理16-特征点匹配,三维数据处理,Open3d,算法,python
基于Open3D的点云处理16-特征点匹配,三维数据处理,Open3d,算法,python

基于Color ICP的点云匹配 参考


import open3d as o3d
import numpy as np
import copy

def draw_registration_result_original_color(source, target, transformation):
    source_temp = copy.deepcopy(source)
    source_temp.transform(transformation)
    o3d.visualization.draw_geometries([source_temp, target],
                                      zoom=0.5,
                                      front=[-0.2458, -0.8088, 0.5342],
                                      lookat=[1.7745, 2.2305, 0.9787],
                                      up=[0.3109, -0.5878, -0.7468])
print("1. Load two point clouds and show initial pose")
demo_colored_icp_pcds = o3d.data.DemoColoredICPPointClouds()
source = o3d.io.read_point_cloud(demo_colored_icp_pcds.paths[0])
target = o3d.io.read_point_cloud(demo_colored_icp_pcds.paths[1])

# draw initial alignment
current_transformation = np.identity(4)
draw_registration_result_original_color(source, target, current_transformation)

# point to plane ICP
current_transformation = np.identity(4)
print("2. Point-to-plane ICP registration is applied on original point")
print("   clouds to refine the alignment. Distance threshold 0.02.")
result_icp = o3d.pipelines.registration.registration_icp(
    source, target, 0.02, current_transformation,
    o3d.pipelines.registration.TransformationEstimationPointToPlane())
print(result_icp)
draw_registration_result_original_color(source, target,
                                        result_icp.transformation)

# colored pointcloud registration
# This is implementation of following paper
# J. Park, Q.-Y. Zhou, V. Koltun,
# Colored Point Cloud Registration Revisited, ICCV 2017
voxel_radius = [0.04, 0.02, 0.01]
max_iter = [50, 30, 14]
current_transformation = np.identity(4)
print("3. Colored point cloud registration")
for scale in range(3):
    iter = max_iter[scale]
    radius = voxel_radius[scale]
    print([iter, radius, scale])

    print("3-1. Downsample with a voxel size %.2f" % radius)
    source_down = source.voxel_down_sample(radius)
    target_down = target.voxel_down_sample(radius)

    print("3-2. Estimate normal.")
    source_down.estimate_normals(
        o3d.geometry.KDTreeSearchParamHybrid(radius=radius * 2, max_nn=30))
    target_down.estimate_normals(
        o3d.geometry.KDTreeSearchParamHybrid(radius=radius * 2, max_nn=30))

    print("3-3. Applying colored point cloud registration")
    result_icp = o3d.pipelines.registration.registration_colored_icp(
        source_down, target_down, radius, current_transformation,
        o3d.pipelines.registration.TransformationEstimationForColoredICP(),
        o3d.pipelines.registration.ICPConvergenceCriteria(relative_fitness=1e-6,
                                                          relative_rmse=1e-6,
                                                          max_iteration=iter))
    current_transformation = result_icp.transformation
    print(result_icp)
draw_registration_result_original_color(source, target,
                                        result_icp.transformation)





配准前:
基于Open3D的点云处理16-特征点匹配,三维数据处理,Open3d,算法,python

基于点到平面icp的配准:
基于Open3D的点云处理16-特征点匹配,三维数据处理,Open3d,算法,python

基于color icp的配准结果:
基于Open3D的点云处理16-特征点匹配,三维数据处理,Open3d,算法,python

基于fpfh特征的点云匹配

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.706, 0])
    target_temp.paint_uniform_color([0, 0.651, 0.929])
    source_temp.transform(transformation)
    o3d.visualization.draw_geometries([source_temp, target_temp],
                                      zoom=0.4559,
                                      front=[0.6452, -0.3036, -0.7011],
                                      lookat=[1.9892, 2.0208, 1.8945],
                                      up=[-0.2779, -0.9482, 0.1556])
    
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 prepare_dataset(voxel_size):
    print(":: Load two point clouds and disturb initial pose.")

    demo_icp_pcds = o3d.data.DemoICPPointClouds()
    source = o3d.io.read_point_cloud(demo_icp_pcds.paths[0])
    target = o3d.io.read_point_cloud(demo_icp_pcds.paths[1])
    trans_init = np.asarray([[0.0, 0.0, 1.0, 0.0], [1.0, 0.0, 0.0, 0.0],
                             [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 0.0, 1.0]])
    source.transform(trans_init)
    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)
    return source, target, source_down, target_down, source_fpfh, target_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

voxel_size = 0.05  # means 5cm for this dataset
source, target, source_down, target_down, source_fpfh, target_fpfh = prepare_dataset(
    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)

匹配前:
基于Open3D的点云处理16-特征点匹配,三维数据处理,Open3d,算法,python
匹配结果:
基于Open3D的点云处理16-特征点匹配,三维数据处理,Open3d,算法,python文章来源地址https://www.toymoban.com/news/detail-690676.html

到了这里,关于基于Open3D的点云处理16-特征点匹配的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Open3D点云数据处理(一):VSCode配置python,并安装open3d教程

    专栏地址:https://blog.csdn.net/weixin_46098577/category_11392993.html 在很久很久以前,我写过这么一篇博客,讲的是open3d点云处理的基本方法。👇 当时是 PyCharm + Anaconda + python3.8 + open3d 0.13 已经是2023年了,现在有了全新版本。目前python由当年的3.8更新到了3.11版本,open3d也从0.13来到了

    2024年02月07日
    浏览(65)
  • 点云处理库Open3D基础操作1

    欢迎访问个人网络日志🌹🌹知行空间🌹🌹 Open3D 是英特尔公司于 2015 年发布的开源 3D 视觉算法库,截至2023年03月已经更新到了 0.17.0 版本。基于 MIT 协议开源许可。 其后端使用 C++11 实现,经过了高度优化,使用 OpenMP 并行运算优化。通过 Python Pybinding ,其提供前端 Python API

    2024年02月10日
    浏览(40)
  • 『OPEN3D』1.1 点云处理 python篇

    目录 1.open3d中的点云IO 2.点云的可视化 3 点云voxel下采样 4. 顶点法线估计 5.最小外界矩 6. 凸包计算 7. 点云距离计算 8. DBSCAN clustering聚类 9. RANSAC(Random Sample Consensus)  10. 点云平面分割 11. 隐藏点移除 12.outliers移除 13 最远点采样(Farthest Point Sample) 专栏地址:https://blog.csdn.net/

    2024年02月02日
    浏览(39)
  • 【点云处理教程】00计算机视觉的Open3D简介

            Open3D 是一个开源库,使开发人员能够处理 3D 数据。它提供了一组用于 3D 数据处理、可视化和机器学习任务的工具。该库支持各种数据格式,例如 .ply、.obj、.stl 和 .xyz,并允许用户创建自定义数据结构并在程序中访问它们。 Open3D 广泛应用于机器人、增强现实和自

    2024年02月14日
    浏览(47)
  • Open3D点云数据处理(二十):最小二乘直线拟合(三维)

    专栏目录:Open3D点云数据处理(Python) 最小二乘三维直线拟合的原理是通过最小化数据点到直线距离的平方和,找到最优的直线模型来拟合给定数据集。这个距离是指数据点到直线的垂线距离。 三维直线通常表示为两个平面的交线,形如 { A

    2024年02月12日
    浏览(52)
  • Open3D点云数据处理(十九):最小二乘直线拟合(矩阵方程法)

    专栏目录:Open3D点云数据处理(Python) 最小二乘直线拟合是一种常用的数据拟合方法,它的目标是找到一条直线,使得该直线和样本数据之间的误差平方和最小。从矩阵方程的角度来看,最小二乘直线拟合可以看作是求解一个超定线性方程组的问题。 具体来说,我们假设有

    2024年02月13日
    浏览(52)
  • open3d点云平移

    功能简介 open3d中点云的平移函数为:pcd.translate((tx, ty, tz), relative=True)。当relative为True时,(tx, ty, tz)表示点云平移的相对尺度,也就是平移了多少距离。当relative为False时,(tx, ty, tz)表示点云中心(质心)平移到的指定位置。质心可以坐标可以通过pcd.get_center()得到。 代码

    2024年01月22日
    浏览(80)
  • Open3d点云对象详解

    PointCloud 是open3d中用于点云处理的类,封装了包括几何变换、数据滤波、聚类分割等一系列实用算法。如无特别说明,本例中所有例程均基于斯坦福兔子的点云模型,下载地址:斯坦福标准模型 读取和清除点云 一般点云数据的读取方法属于 open3d.io 的内容,但点云类也提供了

    2023年04月19日
    浏览(87)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包