open3d ICP 配准

文章目录

  • Three common registration techniques
    • Point-to-point technique
    • Point-to-plane registration
  • ICP registration
    • Helper visualization function
    • Input
    • Global registration
      • Extract geometric feature
      • Input
      • RANSAC
    • Point-to-point ICP
    • Point-to-plane ICP
  • References

Three common registration techniques

假设有一个点集 P \boldsymbol{P} P 在源表面 S P \mathcal{S}_P SP,另一个点集 Q \boldsymbol{Q} Q 在目的表面 S Q \mathcal{S}_Q SQ。如果在每个表面都有 K K K 个点,那么配准问题可以看作一个刚体变换 T = [ R ∣ t ] \boldsymbol{T}=[\boldsymbol{R}|\boldsymbol{t}] T=[Rt],最小化下面的对准误差: ϵ = ∑ k = 1 K ∥ Q k − ( R P k + t ) ∥ 2 \epsilon=\sum_{k=1}^K \| \boldsymbol{Q}_k-(\boldsymbol{R}\boldsymbol{P}_k+\boldsymbol{t})\|^2 ϵ=k=1KQk(RPk+t)2

在这里插入图片描述

Point-to-point technique

从源表面的一点 p \boldsymbol{p} p 出发,p2p 寻找目的表面上最近的点 q \boldsymbol{q} q d s d_s ds 代表两点之间的距离。为了找到最近点,通常会采用 kd-tree 来进行搜索。

Point-to-plane registration

从源点的法向量寻找目的表面的交叉点。如上图 (b) 所示,点 q ′ \boldsymbol{q}' q 是点 p \boldsymbol{p} p 在点 q \boldsymbol{q} q正切平面上的投影。

ICP registration

输入:两个点云及一个初始的可以大致对准两个点云的变换矩阵;

输出:可以准确对准两个点云的变换矩阵。

Helper visualization function

下面的函数可视化目标点云和经过变换后的源点云:

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.4459,
                                      front=[0.9288, -0.2951, -0.2242],
                                      lookat=[1.6784, 2.0612, 1.4451],
                                      up=[-0.3402, -0.9189, -0.1996])

因为函数 transformpaint_uniform_color 会改变原始点云,因此这里用深拷贝 copy.deepcopy 来“保护”原始点云。

Input

下面的代码从两个文件中分别读入源点云和目标点云,并给出了一个初始变换矩阵。

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])
threshold = 0.02
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]])
draw_registration_result(source, target, trans_init)

下面的函数 evaluate_registration 主要计算两个指标:

  • fitness:衡量重叠区域的大小(# of inlier correspondences / # of points in target),越大越好
  • inlier_rmse:计算所有 inlier correspondences 的 RMSE,越小越好

初始的变换矩阵通常通过一个全局的配准算法得到。

Global registration

Extract geometric feature

下采样点云,估计法向量,然后对每个点计算 FPFH 特征。FPFH 特征是一个 33 维的向量,它可以描述一个点的局部几何性质。

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

Input

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

RANSAC

在每个 RANSAC 的迭代中,ransac_n 个随机点从源点云中被选出。它们在目标点云中的对应点通过查询 33 维的 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
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)

之后我们就需要用点到点的 ICP 或者点到面的 ICP 来进一步提升配准精度。

Point-to-point ICP

从以下两步骤中进行迭代:

  1. 从目标点云 P \boldsymbol{P} P 中寻找对应点集 K = { ( p , q ) } \mathcal{K}=\{(\boldsymbol{p},\boldsymbol{q})\} K={(p,q)},源点云通过现有的变换矩阵 T \boldsymbol{T} T 进行变换;
  2. 通过最小化目标函数 E ( T ) E(\boldsymbol{T}) E(T) 来更新变换矩阵 T \boldsymbol{T} T。不同的 ICP 变体会采用不同的目标函数 E ( T ) E(\boldsymbol{T}) E(T),这里使用如下的目标函数 E ( T ) = ∑ ( p , q ) ∈ K ∥ p − T q ∥ 2 E(\boldsymbol{T})=\sum_{(\boldsymbol{p},\boldsymbol{q})\in \mathcal{K}} \|\boldsymbol{p}-\boldsymbol{T}\boldsymbol{q} \|^2 E(T)=(p,q)KpTq2
print("Apply point-to-point ICP")
reg_p2p = o3d.pipelines.registration.registration_icp(
    source, target, threshold, trans_init,
    o3d.pipelines.registration.TransformationEstimationPointToPoint())
print(reg_p2p)
print("Transformation is:")
print(reg_p2p.transformation)
draw_registration_result(source, target, reg_p2p.transformation)

默认情况下,registration_icp 会运行直到收敛或者达到了默认最大迭代次数(30)。 也可以指定最大的迭代次数:

reg_p2p = o3d.pipelines.registration.registration_icp(
    source, target, threshold, trans_init,
    o3d.pipelines.registration.TransformationEstimationPointToPoint(),
    o3d.pipelines.registration.ICPConvergenceCriteria(max_iteration=2000))
print(reg_p2p)
print("Transformation is:")
print(reg_p2p.transformation)
draw_registration_result(source, target, reg_p2p.transformation)

Point-to-plane ICP

点到面的 ICP 采用下面的目标函数:
E ( T ) = ∑ ( p , q ) ∈ K ( ( p − T q ) ⋅ n p ) 2 E(\boldsymbol{T})=\sum_{(\boldsymbol{p},\boldsymbol{q})\in \mathcal{K}} ((\boldsymbol{p}-\boldsymbol{T}\boldsymbol{q})\cdot \boldsymbol{n}_p)^2 E(T)=(p,q)K((pTq)np)2
n p \boldsymbol{n}_p np 代表每个点 p \boldsymbol{p} p 的法向量。点到面 ICP 比点到点 ICP 有更快的收敛速度。

print("Apply point-to-plane ICP")
reg_p2l = o3d.pipelines.registration.registration_icp(
    source, target, threshold, trans_init,
    o3d.pipelines.registration.TransformationEstimationPointToPlane())
print(reg_p2l)
print("Transformation is:")
print(reg_p2l.transformation)
draw_registration_result(source, target, reg_p2l.transformation)

References

[1] open3d 官方文档,http://www.open3d.org/docs/release/tutorial/pipelines/icp_registration.html

[2] Park, S.-Y & Subbarao, M… (2003). A fast Point-to-Tangent Plane technique for multi-view registration. Fourth IEEE International Conference on 3-D Digital Imaging and Modeling. 500. 276- 283. 10.1109/IM.2003.1240260.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/168728.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

搭建Android自动化python+appium环境

一. 需要软件 JDK:JAVA安装后配置JDK环境 SDK:SDK下载后配置adb环境 Python:pyhton语言 Pycharm:python脚本编译工具 Appium-python-client:pyhton中的库Appium客户端 二. 搭建步骤 1.配置JDK环境 ①. 下载安装java: https://www.oracle.com/java/technologies/javase-j…

语音特征提取: 梅尔频谱(Mel-spectrogram)与梅尔倒频系数(MFCCS)

1 核心概念 1.1 语音信号 语音信号是一个非平稳的时变信号,但语音信号是由声门的激励脉冲通过声道形成的,经过声道(人的三腔,咽口鼻)的调制,最后由口唇辐射而出。认为“短时间”(帧长/窗长:10~30ms)内语音信号是平稳…

Unity中Shader法线贴图(下)理论篇

文章目录 前言一、采样出错的原因二、切线空间是什么?切线空间图解: 三、计算方式1、统一变换到切线空间下进行计算2、统一变换到世界空间下进行计算 四、一般统一变换到世界空间下的坐标进行计算1、求M^-1^2、求出n~w~ 前言 这篇文章,主要解…

【Kettle实战】字符串处理及网络请求JSON格式处理

经过大量的kettle操作实践,我们会渐渐掌握一些技巧,大大减轻清洗的工作量。比如在哪里 处理字符串更方便,在哪儿处理更合理都是一个取舍问题。 字符串拼接 MySQL中使用concat(字段1,字段2),但是如果“字段2”为NULL,结…

如何挖掘xss漏洞

如何挖掘xss漏洞 对于如何去挖掘一个xss漏洞我是这样理解的 在实战情况下不能一上来就使用xss语句来进行测试很容易被发现 那这种情况该怎么办呢 打开准备渗透测试的web网站,寻找可以收集用户输入的地方比如搜索框,url框等 发现后寻找注入点 选在输入…

【Q1—45min】

1.epoll除了边沿触发还有什么?与select区别. epoll 是Linux平台下的一种特有的多路复用IO实现方式,与传统的 select 相比,epoll 在性能上有很大的提升。 epoll是一种当文件描述符的内核缓冲区非空的时候,发出可读信号进行通知&…

Find My蓝牙耳机|苹果Find My技术与耳机结合,智能防丢,全球定位

蓝牙耳机就是将蓝牙技术应用在免持耳机上,让使用者可以免除恼人电线的牵绊,自在地以各种方式轻松通话。自从蓝牙耳机问世以来,一直是行动商务族提升效率的好工具。正是应为蓝牙耳机小巧无线,人们越来越喜欢随身携带蓝牙耳机出门&a…

人民网_领导留言板data2022年-2023年

人民网_领导留言板data_2022年全年-2023年11月数据_全国任意城市 包含且不限于:留言ID,留言对象,留言标题,种类名,领域名,目前状态,留言日期,留言内容,回复机构,回复时间,回复内容,满意度,解决力度,沟通态度,办理时效 对于有需要爬取领导留言板的朋友,…

【Qt开发流程之】布局管理

介绍 一个界面呈现,如果要让用户有更好的观感,布局必不可少。 【Qt之布局】QVBoxLayout、QHBoxLayout、QGridLayout、QFormLayout介绍及使用 链接: https://blog.csdn.net/MrHHHHHH/article/details/133915208 qt布局类图: Qt布局是Qt图形…

echarts的使用

1. 普通版 其实主要就是option1&#xff0c;option1就是画的图 echats不能响应刷新&#xff0c;要想实时刷新监听刷新的值重新调用一下方法即可 html <div class"echart" style"width: 100%;height: calc(100% - 130px)" ref"main1">&l…

生物医药行业密钥管理系统特点 安当加密

生物医药行业密钥管理系统的特点主要表现在以下几个方面&#xff1a; 安全性&#xff1a;生物医药行业涉及的数据往往具有极高的私密性和敏感性&#xff0c;因此&#xff0c;密钥管理系统必须具备极高的安全性。这包括对密钥的生成、存储、传输和使用等各个环节进行严格的管理和…

广州一母婴店因设置0元购导致关店

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 广州的一家母婴用品网店Minitutu因双十一优惠券设置错误&#xff0c;导致所有商品变成0元购买&#xff0c;引发消费者疯狂抢购&#xff0c;15万多单订单中有800多万元的损失。店家无奈之下只能暂停营…

亚马逊,shopee,lazada自养号测评:提高店铺曝光,增加产品销量

如何在较短的时间内让自己的店铺排名升高&#xff0c;提高产品销量&#xff0c;除了依靠选品和广告之外&#xff0c;亚马逊测评 在店铺的运营中也是必不可少的环节。 自养号测评对亚马逊卖家来说&#xff0c;是运营店铺的重要手段之一。一个产品想要有更好的曝光、更高的转化率…

优卡特脸爱云一脸通智慧管理平台权限绕过漏洞复现【CVE-2023-6099】

优卡特脸爱云一脸通智慧管理平台权限绕过漏洞复现【CVE-2023-6099】 一、 产品简介二、 漏洞概述三、 影响范围四、 复现环境五、 漏洞复现手动复现自动化复现(小龙POC开源) 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信…

OSCP系列靶场-Esay-DC-1

目录 总结 准备工作 信息收集-端口扫描 目标开放端口收集 目标端口对应服务探测 信息收集-端口测试 22-SSH端口的信息收集 22-SSH端口版本信息与MSF利用(pass) 22-SSH手动登录尝试(失败) 22-SSH弱口令爆破(爆破着玩) 80-HTTP端口的信息收集 信息收集-网站指纹 漏洞…

水库大坝安全监测系统守护水利工程安全的坚实后盾

WX-WY1 随着社会经济的发展和科技的进步&#xff0c;水利工程的安全问题越来越受到人们的关注。水库大坝作为水利工程的重要组成部分&#xff0c;其安全状况直接关系到周边地区人民的生命财产安全和生态环境。因此&#xff0c;建立一个高效、可靠的水库大坝安全监测系统至关重要…

【2021集创赛】NI杯三等奖:基于IECUBE-3100的高精度数模转换器设计及自动化测试方案

本作品参与极术社区组织的有奖征集|秀出你的集创赛作品风采,免费电子产品等你拿~活动。 杯赛题目&#xff1a;DAC芯片测试 参赛要求&#xff1a;本科生组 赛题内容&#xff1a; NIC公司最近正在竞争一个8bit DAC芯片设计的订单机会&#xff0c;需要按照甲方需求尽快提交芯片的设…

二百零四、Flume——登录监听窗口报错Ncat: bind to :::44444: Address already in use. QUITTING.

一、目的 Flume安装好后测试开启监听窗口44444&#xff0c;结果报错Ncat: bind to :::44444: Address already in use. QUITTING. 二、报错详情 Ncat: bind to :::44444: Address already in use. QUITTING. 三、报错原因 经过分析发现&#xff0c;44444窗口已经被占用 […

在UOS系统中编译CEF源码

一、下载cef代码 git clone gitbitbucket.org:chromiumembedded/cef.git 二、执行自动下载代码 由于chromium的代码很大&#xff0c;至少需要准备大概80G的硬盘&#xff01;&#xff01;&#xff01;整个代码量太大还是多准备一些空间吧&#xff08;强烈建议使用固态硬盘保存否…

如何在外部数据库中存储空间化表时使用Mapinfo_mapcatalog

开始创建地图目录表之前 您将使用EasyLoader在要使用的数据库中创建地图目录表。EasyLoader与MapInfo Pro一起安装。 &#xff08;工具“DBMS_Catalog”不再随MapInfo Professional 64位一起提供&#xff0c;因为它的功能可以在EasyLoader工具中找到。&#xff09; ​ 注&…