Python Open3D点云配准点对点,点对面ICP(Iterative Closest Point)

news2024/9/22 11:31:11

Python Open3D点云配准 ICP(Iterative Closest Point)

这篇博客将介绍 迭代最近点配准算法(Iterative Closest Point, ICP) 。多年来,它一直是研究和工业中几何注册的支柱。输入是两个点云和一个初始变换,该变换大致将源点云与目标点云对齐。输出是一个精确的变换,它将两个点云紧密对齐。

  • 将展示俩种ICP:点对点ICP(PointToPoint)和点对面ICP(PointToPlane)。
  • 函数 draw_registration_result 在icp过程中可视化对齐效果。目标点云和源点云分别用青色和黄色绘制。两个点云彼此重叠得越多越紧密,对齐结果越好。
  • 函数 evaluate_registration 计算两个主要指标:
    • fitness:其测量重叠区域(内部对应的数量/目标中的点的数量),越高越好。
    • inlier_rmse,其测量所有inlier对应的rmse相似性,越低越好。

1. 效果图

原始点云黄色 VS 原始点云青色:
在这里插入图片描述

初始对齐 Point to Point ICP 匹配74056个点,效果图如下:

Apply point-to-point ICP
RegistrationResult with fitness=3.724495e-01, inlier_rmse=7.760179e-03, and correspondence_set size of 74056
Access transformation to get result.
Transformation is:
[[ 0.83924644 0.01006041 -0.54390867 0.64639961]
[-0.15102344 0.9
6521988 -0.21491604 0.75166079]
[ 0.52191123 0.2616952 0.81146378 -1.50303533]
[ 0. 0. 0. 1. ]]

在这里插入图片描述

Point to Plane ICP 匹配123471个点效果图如下:
可以看到点对面ICP更快达到收敛。fitness更高更好,inlier_rmse也小一些。

Apply point-to-plane ICP
RegistrationResult with fitness=6.209722e-01, inlier_rmse=6.581453e-03, and correspondence_set size of 123471
Access transformation to get result.
Transformation is:
[[ 0.84023324 0.00618369 -0.54244126 0.64720943]
[-0.14752342 0.96523919 -0.21724508 0.81018928]
[ 0.52132423 0.26174429 0.81182576 -1.48366001]
[ 0. 0. 0. 1. ]]

在这里插入图片描述

Initial alignment
RegistrationResult with fitness=1.747228e-01, inlier_rmse=1.177106e-02, and correspondence_set size of 34741
Access transformation to get result. 

Apply point-to-point ICP
RegistrationResult with fitness=3.724495e-01, inlier_rmse=7.760179e-03, and correspondence_set size of 74056
Access transformation to get result.
Transformation is:
[[ 0.83924644  0.01006041 -0.54390867  0.64639961]
 [-0.15102344  0.9
 6521988 -0.21491604  0.75166079]
 [ 0.52191123  0.2616952   0.81146378 -1.50303533]
 [ 0.          0.          0.          1.        ]] 

Apply point-to-plane ICP
RegistrationResult with fitness=6.209722e-01, inlier_rmse=6.581453e-03, and correspondence_set size of 123471
Access transformation to get result.
Transformation is:
[[ 0.84023324  0.00618369 -0.54244126  0.64720943]
 [-0.14752342  0.96523919 -0.21724508  0.81018928]
 [ 0.52132423  0.26174429  0.81182576 -1.48366001]
 [ 0.          0.          0.          1.        ]] 

2. 安装及原理

pip install open3d -i http://mirrors.aliyun.com/pypi/simple/

点云配准本质上是将点云从一个坐标系变换到另一个坐标系。通常会需要用到两个点云数据,第一类点云数据称为原始点云,用S(source)来表示,黄色。第二类点云数据称为目标点云,用T(Target)来表示,青色。

点云配准的主要任务是计算出旋转矩阵R和平移矩阵T。

2.1 点对点ICP

通常,ICP算法迭代两个步骤:

  • 查找对应集K={(p,q)} 从目标点云P和用当前变换矩阵T变换的源点云Q中提取并更新转换T
  • 通过最小化在对应集K上定义的目标函数E(T)
    ICP的不同变体使用不同的目标函数E(T):

E ( T ) = ∑ ( p , q ) ϵ κ ∣ ∣ p − T q ∣ ∣ 2 \bold {E(T)=\sum_{(p,q)\epsilon\kappa} \mid\mid p-T_q \mid \mid ^2 } E(T)=(p,q)ϵκpTq2

TransformationEstimationPointToPoint类提供了计算点对点ICP目标的残差和转换矩阵的函数。函数registration_icp将其作为参数并运行点对点icp以获得结果。

fitness分数从0.174723增加到0.372450。inlier_rmse从0.011771减少到0.007760。默认情况下,registration_icp 运行直到收敛或达到最大迭代次数(默认情况下为30)。它可以被改变以允许更多的计算时间并进一步改进结果。

最终对准是紧密的。fitness分数提高到0.621123。inlier_rmse降低到0.006583。

2.2 点对面ICP

点对面ICP使用不同的目标函数E(T):
E ( T ) = ∑ ( p , q ) ϵ κ ( ( p − T q ) ⋅ n p ) 2 \bold {E(T)=\sum_{(p,q)\epsilon\kappa} ((p-T_q) \cdot n_p)^2} E(T)=(p,q)ϵκ((pTq)np)2

其中 n p n_p np 是点p的法线,表明点对平面ICP算法比点对点ICP算法具有更快的收敛速度。
使用不同的参数TransformationEstimationPointToPlane调用registration_icp。在内部,此类实现了计算点到平面ICP目标的残差和转换矩阵的函数。

3. 源码

# 使用官方demo点云对俩个原始点云进行点对点icp,点对面icp配准,并进行可视化,原始点云黄色,目标点云青色。
# python icp_registration.py
import copy

import numpy as np
import open3d as o3d


def draw_registration_result(source, target, transformation, title):
    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([source_temp, target_temp], title="Open3D " + title)


def point_to_point_icp(source, target, threshold, trans_init):
    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, "\n")
    draw_registration_result(source, target, reg_p2p.transformation, 'point-to-point ICP')


def point_to_plane_icp(source, target, threshold, trans_init):
    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, "\n")
    draw_registration_result(source, target, reg_p2l.transformation, 'point-to-plane ICP')


if __name__ == "__main__":
    # 本地没有会自动下载demo点云数据 https://github.com/isl-org/open3d_downloads/releases/download/20220301-data/DemoICPPointClouds.zip
    pcd_data = o3d.data.DemoICPPointClouds()
    source = o3d.io.read_point_cloud(pcd_data.paths[0])
    target = o3d.io.read_point_cloud(pcd_data.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, 'origin')

    print("Initial alignment")
    # 函数evaluate_registration计算两个主要指标:
    # fitness:其测量重叠区域(内部对应的数量/目标中的点的数量),越高越好。
    # inlier_rmse,其测量所有inlier对应的rmse相似性,越低越好。
    evaluation = o3d.pipelines.registration.evaluate_registration(
        source, target, threshold, trans_init)
    print(evaluation, "\n")

    point_to_point_icp(source, target, threshold, trans_init)
    point_to_plane_icp(source, target, threshold, trans_init)

参考

  • http://www.open3d.org/docs/release/tutorial/pipelines/icp_registration.html
  • http://www.open3d.org/docs/release/python_example/pipelines/index.html#colored-icp-registration-py
  • https://github.com/seminar2012/Open3D
  • http://www.open3d.org/docs/release/getting_started.html
  • https://blog.csdn.net/suiyingy/article/details/124336448

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

g++多文件编译

g windows 多文件编译 文章目录g windows 多文件编译Examplescenario 1scenario 2方法一 使用 先编译&#xff0c;再连接方法二 直接编译 生成结果文件visual code 配置 tasks.json问题 undefined reference to std::__cxx11::basic_string<char, std::charg编译单个文件时&…

Java基础:线程池

第一章 等待唤醒机制 1.1 线程间通信 概念&#xff1a;多个线程在处理同一个资源&#xff0c;但是处理的动作&#xff08;线程的任务&#xff09;却不相同。 比如&#xff1a;线程A用来生成包子的&#xff0c;线程B用来吃包子的&#xff0c;包子可以理解为同一资源&#xff…

【SpringMVC】入门篇:带你了解SpringMVC的执行流程

目录 一、简介 二、环境的搭建 三、快速入门 四、SpringMVC的执行流程 Spring有关的文章已经全部更新完&#xff0c;收录于我的专栏&#x1f449;Spring&#x1f448; 一、简介我们在前边已经学习了Spring的基本使用。从这节开始&#xff0c;我们进行SpringMVC的学习。在学习之…

汇编算数运算指令

目录 加法类指令 加法指令ADD 加进位的加法指令ADC 带进位有啥用呢&#xff1f; 增量指令INC&#xff08;1&#xff09; 减法类指令 减法指令SUB 带借位减法指令SBB 减量指令DEC 比较指令CMP&#xff08;分支程序设计常用&#xff09; 乘法指令 乘法指令MUL和符号整…

职场经验:自动化测试介绍和分类,看这一篇就够了

什么是自动化测试? 自动化测试是软件测试活动中一个重要的分支和组成部分,即利用工具或脚本达到测试目的,没有人工或者极少人工参与的软件测试活动称为自动化测试. 自动化测试的优势有哪些? 方便进行回归测试,当软件的版本发布比较频繁的时候,自动化的效果很明显 自动处理…

全网第三详细tshark使用帮助

一 前言tshark作为wireshark的命令行版本&#xff0c;功能非常强大&#xff0c;可以抓包&#xff0c;数据包分析、提取文件、提取分析后的数据还支持各种格式&#xff0c;可以说一把流量分析的瑞士军刀&#xff0c;如果在低流量的场景&#xff0c;包装下tshark命令&#xff0c;…

查找树莓派ip地址的几种方法

1.环境说明 从上面的图中可以看到树莓派是通过网线和win10电脑相连的&#xff0c;以此来共享win10电脑网络&#xff0c;但是需要在电脑端设置后才能将网络共享出来&#xff0c; 设置方法参考以下链接&#xff1a; 通过一根网线共享网络给另一个电脑或者群辉上网 注意&#xff0…

jQuery 遍历

什么是遍历&#xff1f; jQuery 遍历&#xff0c;意为"移动"&#xff0c;用于根据其相对于其他元素的关系来"查找"&#xff08;或选取&#xff09;HTML 元素。以某项选择开始&#xff0c;并沿着这个选择移动&#xff0c;直到抵达您期望的元素为止。 下图…

dotnet项目使用Cefsharp与Js互相调用函数

1. 背景 最近在一个项目中使用 CefSharp 加载H5页面, 其中一些业务逻辑需要调用 Js 函数, 同时 Js 也会调用一些 native 函数: 这里我们使用官方的demo代码进行添加修改, 修改后的代码在此: DevWiki/CefSharp.MinimalExample - CefSharp.MinimalExample - DevWiki Gitea 2. J…

Allegro如何打开和关闭飞线操作指导

Allegro如何打开和关闭飞线操作指导 Allegro可以打开和关闭飞线,下面介绍如何打开和关闭飞线,具体操作如下 选择display-show rats-all。打开所有nets的飞线 如下图 如果菜单里面添加图标,可以直接点击图标显示所有飞线 选择display-Blank Rats-all关闭所有nets的飞线 …

Spring MVC学习 | 简介HelloWord

文章目录一、Spring MVC简介1.1 MVC回顾1.2 Spring MVC是神魔二、HelloWord2.1 相关文件的准备2.2 创建请求控制器2.3 创建Spring MVC配置文件2.4 测试HelloWord2.4.1 访问首页2.4.2 访问目标页面2.5 执行流程学习视频&#x1f3a5;&#xff1a;https://www.bilibili.com/video…

STM32G4系列存储访问的两个小话题

一、有关CCM访问地址的话题有用过STM32F4系列部分芯片或STM32F334芯片的人&#xff0c;可能知道片内有个CCM【Core Coupled Memory】区域,从芯片系统框图结合文字说明&#xff0c;可以清晰知道这个区域仅能被CPU访问&#xff0c;常用来存放些对执行效率敏感的关键性的代码或数据…

【mmdetection系列】mmdetection之head讲解

目录 1.configs 2.具体实现 3.调用 3.1 注册 3.2 调用 配置部分在configs/_base_/models目录下&#xff0c;具体实现在mmdet/models/*_heads目录下。 这个heads可以是很多个目录下的。 1.configs 我们看下yolox的head吧。 https://github.com/open-mmlab/mmdetection/b…

Web前端开发技术课程大作业:基于HTML+CSS+JavaScript实现校园主题-萍乡田家炳中学校网站(1页)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

详细讲解Linux物理内存初始化

说明&#xff1a; Kernel版本&#xff1a;4.14ARM64处理器&#xff0c;Contex-A53&#xff0c;双核使用工具&#xff1a;Source Insight 3.5&#xff0c; Visio 1. 介绍 让我们思考几个朴素的问题&#xff1f; 系统是怎么知道物理内存的&#xff1f;在内存管理真正初始化之前…

Java项目:SSM实现的校园门户平台网站系统含开题报告与需求分析

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本系统为前后台项目&#xff0c;后台为管理员登录&#xff0c;前台为社团、学生、教师角色登录&#xff1b; 管理员角色包含以下功能&#xff…

对称加密算法(二)(分组密码,Feistel Cipher)

文章目录Traditional Block Cipher StructureStream Ciphers and Block CiphersFeistel CipherReferencesTraditional Block Cipher Structure Stream Ciphers and Block Ciphers 序列密码也称为流密码 (Stream Ciphers)&#xff0c; 它是指每次对数字数据流的一个比特或一个…

CSS -- CSS复合选择器总结

文章目录CSS的复合选择器1 什么是复合选择器2 后代选择器3 子选择器4 并集选择器5 伪类选择器6 链接伪类选择器7 :focus 伪类选择器8 复合选择器总结CSS的复合选择器 1 什么是复合选择器 在 CSS 中&#xff0c;可以根据选择器的类型把选择器分为基础选择器和复合选择器&#…

【博客554】k8s 中的 Client-Side Apply 和 Server-Side Apply

k8s 中的 Client-Side Apply 和 Server-Side Apply 背景 如果你经常与 kubectl 打交道&#xff0c;那相信你一定见过 kubectl.kubernetes.io/last-applied-configuration annotation&#xff0c;以及那神烦的 managedFields&#xff0c;像这样&#xff1a; kubectl get pods…

单元测试理论储备及JUnit5实战

概述 测试驱动开发&#xff0c;TDD&#xff0c;Test Driven Development&#xff0c;优点&#xff1a; 使得开发人员对即将编写的软件任务具有更清晰的认识&#xff0c;使得他们在思考如何编写代码之前先仔细思考如何设计软件对测试开发人员所实现的代码提供快速和自动化的支…