ICP算法思想与推导详解——什么东西“最近点”,又“迭代”了什么?

2023-10-29

一、什么是ICP

ICP的全称是 iterative closest point —— 迭代最近点。它是一种点云匹配的算法。

在三维重建或者视觉Slam场景中,经常需要确定某一时刻的相机位姿。
相机在运动过程中,不同时刻对同一物体获取的三维点云信息是不同的。
此时我们可以通过点云的对应点在两个时刻间差异来计算相机位姿的改变。
对位姿、相机模型等不了解的可以去看我的VSLAM笔记-相机模型

简而言之,ICP目的就是为了使用某种方法求出两组点云之间的三维旋转与平移矩阵 T \boldsymbol T T

二、算法简介

2.1 场景

通常,我们可以使用一组空间点云数据来表示某一物体,记为 { p i } \{\boldsymbol p_i\} {pi}
在某一时刻,该物体发生了移动与旋转,此时他的空间坐标发生了变化,也就是点云数据 { p i } \{\boldsymbol p_i\} {pi} 的坐标全都发生了变化,新点云坐标记为 { q i } \{\boldsymbol q_i\} {qi}
那么通过学习刚性物体的旋转平移我们可以知道, p i \boldsymbol p_i pi q i \boldsymbol q_i qi 之间存在一定关系:
q i = R p i + t   ,          i = 1 , 2 , … , n 或 q ˉ i = T p ˉ i   ,          i = 1 , 2 , … , n \boldsymbol q_i = \boldsymbol R\boldsymbol p_i + \boldsymbol t~,~~~~~~~~i=1,2,\dots,n \\ 或 \\ \bar {\boldsymbol q}_i = \boldsymbol T \bar{\boldsymbol p}_i~,~~~~~~~~i=1,2,\dots,n qi=Rpi+t ,        i=1,2,,nqˉi=Tpˉi ,        i=1,2,,n

2.2 步骤过程

ICP算法的大致分为两步:

  1. 匹配两个点云 P \boldsymbol P P Q \boldsymbol Q Q ,找出对应的点
  2. R ,   t \boldsymbol R,\ \boldsymbol t R, t

那么此时需要解决的两个问题就是:

  • 问题① 如何查找两个点云之间的相匹配的对应点?
  • 问题② 使用什么方法来求出 R ,   t \boldsymbol R,\ \boldsymbol t R, t

对于问题①

从算法名 “迭代最近点” 我们不难看出,此算法解决第一个问题的基本思想是使用距离最近的点作为匹配点
也就是遍历点云 P \boldsymbol P P 中的所有点,计算它们与点云 Q \boldsymbol Q Q 中每个点的距离,将距离最少的点作为其对应点。

例如查找 p 5 \boldsymbol p_5 p5 的对应点就是计算它与所有 q \boldsymbol q q 的距离,找出距离最近的那个 q \boldsymbol q q
min ⁡ q i { d i s t ( p 5 , q i ) } \min_{\boldsymbol q_i} \Big\{dist(\boldsymbol p_5, \boldsymbol q_i)\Big\} qimin{dist(p5,qi)}

时间复杂度为 O ( n 2 ) O(n^2) O(n2)

找到对应点后,就可以使用一定方法来找出最优的 R ,   t \boldsymbol R,\ \boldsymbol t R, t

注意,这里之所以说是 “最优的” R ,   t \boldsymbol R,\ \boldsymbol t R, t 值,是因为使用最近点匹配方法找出的对应点往往不是真实对应的点:
在这里插入图片描述

求出来的 R ,   t \boldsymbol R,\ \boldsymbol t R, t 自然也不会是最终真正的值。

所以这个时候我们就需要“迭代”,第一次计算得出了一组当前最优的 R ,   t \boldsymbol R,\ \boldsymbol t R, t 值以后,可以将点云 P \boldsymbol P P 经过 R p + t \boldsymbol R\boldsymbol p + \boldsymbol t Rp+t移动到 P ′ \boldsymbol P' P 的位置(就离目标点云 Q \boldsymbol Q Q 近了一些),此时,再对 新的点云 P ′ \boldsymbol P' P 和 点云 Q \boldsymbol Q Q 重复上面的两个步骤即可。

每次迭代都可以式 P \boldsymbol P P 更加靠近 Q \boldsymbol Q Q 直到收敛为止。


对于问题②

通过刚刚分析我们知道:
q i ≠ R p i + t \boldsymbol q_i \neq \boldsymbol R\boldsymbol p_i + \boldsymbol t qi=Rpi+t
实际上:
q i = R p i + t + e i \boldsymbol q_i = \boldsymbol R\boldsymbol p_i + \boldsymbol t + \boldsymbol e_i qi=Rpi+t+ei
(此处是以 point-to-point 方法为例构造误差函数,其中 e i \boldsymbol e_i ei 表示误差)

那么现在的任务其实就是使误差最小,即

min ⁡ R , t ∑ i = 1 n ∣ q i − R p i − t ∣ 或者 min ⁡ R , t 1 2 ∑ i = 1 n ∥ q i − R p i − t ∥ 2 \min_{\boldsymbol R,\boldsymbol t}\sum^n_{i=1}|\boldsymbol q_i - \boldsymbol R\boldsymbol p_i - \boldsymbol t| \\ 或者 \\ \min_{\boldsymbol R,\boldsymbol t}\frac{1}{2}\sum^n_{i=1}\|\boldsymbol q_i - \boldsymbol R\boldsymbol p_i - \boldsymbol t\|^2 R,tmini=1nqiRpit或者R,tmin21i=1nqiRpit2
再使用最小二乘等方式求解 R , t \boldsymbol R,\boldsymbol t R,t 即可


这里讲的是最基本的ICP算法的操作方法
其实对于上面两个问题的处理方法还有很多。

例如
对于问题①,除了使用最近点匹配,还可以使用投影坐标作为对应点匹配,或者融合RGB图像使用特征提取的方法来匹配等等;
对于问题②,常见的ICP构造误差函数的方法有Point-to-Point, Point-to-Plane, Plane-to-Plane等。

另外还有:

  • 点太多了是不是可以采样选取?要如何采样?
  • 是否可以对这些点添加一些权重来提高收敛速度?
  • 有些差异过大的匹配点是否可以剔除掉?如何剔除?
    ……

等等许多问题也是很值得思考的。

ICP感觉是一个极其耗时的过程,所以按照使用场景选对每一步的方法很重要~
前几天刚看的 Kinect Fusion 使用的就是 投影坐标对应点匹配 + Point-to-Plane 方法来求解ICP的

三、 R , t \boldsymbol R,\boldsymbol t R,t 求解推导

常用的求解方法有两种:

  1. SVD求解法
  2. 非线性优化

下面以 Point-to-Point ICP为例推导求解过程

2.1 使用SVD方法求解最优R与t

Point-to-Point 优化误差目标为:
arg ⁡ min ⁡ R , t 1 2 ∑ i = 1 n ∥ q i − R p i − t ∥ 2 \arg\min_{\boldsymbol R,\boldsymbol t}\frac{1}{2}\sum^n_{i=1}\|\boldsymbol q_i - \boldsymbol R\boldsymbol p_i - \boldsymbol t\|^2 argR,tmin21i=1nqiRpit2

提一句:Point-to-Plane的目标函数为 arg ⁡ min ⁡ R , t 1 2 ∑ i = 1 n ∥ ( q i − R p i − t ) ⋅ n i ∥ 2 \arg\displaystyle\min_{\boldsymbol R,\boldsymbol t}\frac{1}{2}\sum^n_{i=1}\|(\boldsymbol q_i - \boldsymbol R\boldsymbol p_i - \boldsymbol t)\cdot\boldsymbol n_i\|^2 argR,tmin21i=1n(qiRpit)ni2 ,其中 n i \boldsymbol n_i ni 为法向量。有兴趣的可以自己查一下资料看看推导过程。


先求 t \boldsymbol t t

记:
e = 1 2 ∑ i = 1 n ∥ q i − R p i − t ∥ 2 \boldsymbol e=\frac{1}{2}\sum^n_{i=1}\|\boldsymbol q_i - \boldsymbol R\boldsymbol p_i - \boldsymbol t\|^2 e=21i=1nqiRpit2
t \boldsymbol t t求导:
∂ e ∂ t = − ( ∑ i = 1 n q i − ∑ i = 1 n R p i − n t ) \frac{\partial\boldsymbol e}{\partial\boldsymbol t}=-\Big(\sum^n_{i=1}\boldsymbol q_i - \sum^n_{i=1}\boldsymbol R\boldsymbol p_i - n\boldsymbol t\Big) te=(i=1nqii=1nRpint)
∂ e ∂ t = 0 \frac{\partial\boldsymbol e}{\partial\boldsymbol t}=0 te=0得到:
t ^ = 1 n ∑ i = 1 n q i − R ⋅ 1 n ∑ i = 1 n p i \hat{\boldsymbol t}=\frac{1}{n}\sum^n_{i=1}\boldsymbol q_i - \boldsymbol R\cdot\frac{1}{n}\sum^n_{i=1}\boldsymbol p_i t^=n1i=1nqiRn1i=1npi
分别记 μ q = 1 n ∑ i = 1 n q i   ,   μ p = 1 n ∑ i = 1 n p i \boldsymbol\mu_q=\displaystyle\frac{1}{n}\sum^n_{i=1}\boldsymbol q_i~, ~\boldsymbol\mu_p=\displaystyle\frac{1}{n}\sum^n_{i=1}\boldsymbol p_i μq=n1i=1nqi , μp=n1i=1npi(很多地方也把它们称作点云的质心),那么上式就变为:
t ^ = μ q − R μ p \hat{\boldsymbol t}=\boldsymbol\mu_q - \boldsymbol R\boldsymbol\mu_p t^=μqRμp


再求 R \boldsymbol R R

t ^ \hat{\boldsymbol t} t^ 带入原误差函数中得:
e = 1 2 ∑ i = 1 n ∥ q i − R p i − ( μ q − R μ p ) ∥ 2 = 1 2 ∑ i = 1 n ∥ q i − μ q − R ( p i − μ p ) ∥ 2 \begin{aligned} \boldsymbol e&=\frac{1}{2}\sum^n_{i=1}\|\boldsymbol q_i - \boldsymbol R\boldsymbol p_i - (\boldsymbol\mu_q - \boldsymbol R\boldsymbol\mu_p)\|^2 \\ &=\frac{1}{2}\sum^n_{i=1}\| \textcolor{#0033CC}{\boldsymbol q_i - \boldsymbol\mu_q} - \boldsymbol R( \textcolor{#BB0000}{\boldsymbol p_i - \boldsymbol\mu_p})\|^2 \end{aligned} e=21i=1nqiRpi(μqRμp)2=21i=1nqiμqR(piμp)2

再分别记 x i = q i − μ q   ,   y i = p i − μ p \boldsymbol x_i=\textcolor{#0033CC}{\boldsymbol q_i - \boldsymbol\mu_q} ~, ~\boldsymbol y_i=\textcolor{#BB0000}{\boldsymbol p_i - \boldsymbol\mu_p} xi=qiμq , yi=piμp (相当于是每个点与其质心的距离,去中心化的操作) 得:
e = 1 2 ∑ i = 1 n ∥ x i − R y i ∥ 2 \boldsymbol e=\frac{1}{2}\sum^n_{i=1}\| \boldsymbol x_i - \boldsymbol R\boldsymbol y_i\|^2 e=21i=1nxiRyi2
所以:
R ^ = arg ⁡ min ⁡ R ∑ i = 1 n ∥ x i − R y i ∥ 2 = arg ⁡ min ⁡ R ∑ i = 1 n ( x i − R y i ) T ( x i − R y i ) = arg ⁡ min ⁡ R ∑ i = 1 n ( x i T x i − x i T R y i − y i T R T x i − y i T R T R y i ) = arg ⁡ min ⁡ R ∑ i = 1 n ( x i T x i − 2 x i T R y i − y i T y i ) = arg ⁡ max ⁡ R ∑ i = 1 n x i T R y i = arg ⁡ max ⁡ R t r ( ∑ i = 1 n x i T R y i ) = arg ⁡ max ⁡ R t r ( ∑ i = 1 n R y i x i T ) = arg ⁡ max ⁡ R t r ( R ∑ i = 1 n y i x i T ) \begin{aligned} \hat{\boldsymbol R}&=\arg\min_{\boldsymbol R}\sum^n_{i=1}\| \boldsymbol x_i - \boldsymbol R\boldsymbol y_i\|^2 \\ &=\arg\min_{\boldsymbol R}\sum^n_{i=1} ( \boldsymbol x_i - \boldsymbol R\boldsymbol y_i) ^\mathrm T( \boldsymbol x_i - \boldsymbol R\boldsymbol y_i) \\ &=\arg\min_{\boldsymbol R}\sum^n_{i=1} ( \boldsymbol x_i^\mathrm T\boldsymbol x_i - \boldsymbol x_i^\mathrm T\boldsymbol R\boldsymbol y_i - \boldsymbol y_i^\mathrm T\boldsymbol R^\mathrm T\boldsymbol x_i - \boldsymbol y_i^\mathrm T\boldsymbol R^\mathrm T\boldsymbol R\boldsymbol y_i) \\ &=\arg\min_{\boldsymbol R}\sum^n_{i=1} ( \boldsymbol x_i^\mathrm T\boldsymbol x_i - 2\boldsymbol x_i^\mathrm T\boldsymbol R\boldsymbol y_i - \boldsymbol y_i^\mathrm T\boldsymbol y_i) \\ &=\arg\max_{\boldsymbol R}\sum^n_{i=1}\boldsymbol x_i^\mathrm T\boldsymbol R\boldsymbol y_i \\ &=\arg\max_{\boldsymbol R}tr\Big(\sum^n_{i=1}\boldsymbol x_i^\mathrm T\boldsymbol R\boldsymbol y_i\Big) \\ &=\arg\max_{\boldsymbol R}tr\Big(\sum^n_{i=1}\boldsymbol R\boldsymbol y_i\boldsymbol x_i^\mathrm T\Big) \\ &=\arg\max_{\boldsymbol R}tr\Big(\boldsymbol R\sum^n_{i=1}\boldsymbol y_i\boldsymbol x_i^\mathrm T\Big) \end{aligned} R^=argRmini=1nxiRyi2=argRmini=1n(xiRyi)T(xiRyi)=argRmini=1n(xiTxixiTRyiyiTRTxiyiTRTRyi)=argRmini=1n(xiTxi2xiTRyiyiTyi)=argRmaxi=1nxiTRyi=argRmaxtr(i=1nxiTRyi)=argRmaxtr(i=1nRyixiT)=argRmaxtr(Ri=1nyixiT)

上面的 t r tr tr 表示矩阵的迹
最后这个 y i x i T \boldsymbol y_i\boldsymbol x_i^\mathrm T yixiT实际上是个协方差矩阵

H = ∑ i = 1 n y i x i T \boldsymbol H=\displaystyle\sum^n_{i=1}\boldsymbol y_i\boldsymbol x_i^\mathrm T H=i=1nyixiT ,有:
R ^ = arg ⁡ max ⁡ R t r ( R H ) \hat{\boldsymbol R}=\arg\max_{\boldsymbol R}tr\Big(\boldsymbol R\boldsymbol H\Big) R^=argRmaxtr(RH)

现在对 H \boldsymbol H H进行SVD分解可得:
H = U Σ V T \boldsymbol H=\boldsymbol U\boldsymbol\Sigma\boldsymbol V^\mathrm T H=UΣVT
则:
R ^ = arg ⁡ max ⁡ R t r ( R U Σ V T ) = arg ⁡ max ⁡ R t r ( Σ V T R U ) \begin{aligned} \hat{\boldsymbol R}&=\arg\max_{\boldsymbol R}tr\Big(\boldsymbol R\boldsymbol U\boldsymbol\Sigma\boldsymbol V^\mathrm T\Big) \\ &=\arg\max_{\boldsymbol R}tr\Big(\boldsymbol\Sigma\boldsymbol V^\mathrm T\boldsymbol R\boldsymbol U\Big) \end{aligned} R^=argRmaxtr(RUΣVT)=argRmaxtr(ΣVTRU)

M = V T R U \boldsymbol M=\boldsymbol V^\mathrm T\boldsymbol R\boldsymbol U M=VTRU,又 Σ \boldsymbol\Sigma Σ 是对角阵
那么:
R ^ = arg ⁡ max ⁡ R t r ( Σ M ) = arg ⁡ max ⁡ R t r ( ∑ i = 1 n σ i m i i ) \begin{aligned} \hat{\boldsymbol R}&=\arg\max_{\boldsymbol R}tr\Big(\boldsymbol\Sigma\boldsymbol M\Big) \\ &=\arg\max_{\boldsymbol R}tr\Big(\sum^n_{i=1}\sigma_i m_{ii}\Big) \end{aligned} R^=argRmaxtr(ΣM)=argRmaxtr(i=1nσimii)

因为 V T , R , U \boldsymbol V^\mathrm T,\boldsymbol R,\boldsymbol U VT,R,U 均为正交矩阵,所以 M \boldsymbol M M是正交矩阵,则 m i j ≤ 1 m_{ij}\le1 mij1
故当 m i i = 1 m_{ii}=1 mii=1 时, ∑ i = 1 n σ i m i i \displaystyle\sum^n_{i=1}\sigma_i m_{ii} i=1nσimii取到最大值。
M \boldsymbol M M 是正交矩阵,所以
M = I \boldsymbol M=\boldsymbol I M=I

V T R U = I \boldsymbol V^\mathrm T\boldsymbol R\boldsymbol U=\boldsymbol I VTRU=I
所以
R ^ = V U T \hat{\boldsymbol R}=\boldsymbol V\boldsymbol U^\mathrm T R^=VUT

至此,求得最优的 R \boldsymbol R R t \boldsymbol t t

2.2 使用非线性优化求解

此方法比较复杂,可以看我的VSLAM笔记-BundleAdjustment


懒得写参考资料了,好麻烦 >.>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ICP算法思想与推导详解——什么东西“最近点”,又“迭代”了什么? 的相关文章

随机推荐

  • 各种开源协议

    来源 玩转嵌入式 今天跟大家分享一些开源协议的知识 这些协议缩写词在各种代码 文档中随处可见 可又有多少人对这些知识细细研究过呢 作为一名专业的嵌入式系统开发人员这些东西都是一种素养 特别是当你自己要开源一些东西的时候该如何选择开源协议就变
  • 一个移植十分方便的malloc函数族的实现

    相信学习过c语言的人都知道malloc free函数 这里就不多说怎么用了 这里要说的是 提供它们的实现 该实现方法由uboot中malloc等函数的实现改编而来 已经过验证 没有问题 多说一句 该实现支持物理地址malloc free 不
  • Vue 使用 Markdown标记语言编辑器(MavonEditor)

    文章目录 1 实现效果 2 直接撸 MavonEditor 上代码 2 1 npm安装 MavonEditor 2 2 在需要使用Markdown的Vue组件导入mavonEditor 2 3 vue页面使用 3 参考 1 实现效果 本篇文
  • 7-10倍写入性能提升:剖析WiredTiger数据页无锁及压缩黑科技

    导语 计算机硬件在飞速发展 数据规模在急速膨胀 但是数据库仍然使用是十年以前的架构体系 WiredTiger 尝试打破这一切 充分利用多核与大内存时代来重新设计数据库引擎 达到 7 10 倍写入性能提升 本文由袁荣喜向 高可用架构 投稿 通
  • order by与索引

    ORDER BY 通常会有两种实现方法 一个是利用有序索引自动实现 也就是说利用有序索引的有序性就不再另做排序操作了 另一个是把结果选好之后再排序 用有序索引这种 当然是最快的 不过有一些限制条件 来看下面的测试 测试数据 student表
  • Matplotlib数据可视化

    e 安装及使用 安装 pip install i https mirrors aliyun com pypi simple matplotlib 使用 import Matplotlib pyplot as plt 操作需要numpy数据对
  • uni-app 布局固定头部,内容滚动

    1 代码
  • ios部分机型出现select、input等控件点击后失效不可再次点击dug

    问题描述 在昨天晚上的时候测试突然告诉我一个问题 在iphone 6s中select选择器在第一次点击后 其他的选择无法点击 整个手机都属于暂时性死机状态 问题分析 当时首先对代码进行了排查 排除是逻辑方面的问题 经过多方面验证发现只有6s
  • TensorFlow笔记:激活函数

    tf nn sigmid 函数 函数表达式 f x 1 1
  • h5+js+ajax+百度翻译API:实现翻译功能

    使用前端技术 h5 js ajax开发网页翻译功能 调用百度开放平台的API 入门级前端demo 非常详细好入手 功能为 点击Translate按钮 实现英译汉 页面如下 一 appID和key值准备 在百度开放平台https api fa
  • popState 监听浏览器切换路由

    浏览器内 popState 监听器使用 在前端开发过程中 在一些业务场景中可能会遇到监听浏览器前进 后退 控制路由等情况 我们可以使用Web API提供的popState事件来处理这些情况 提到popState 应用中 通常pushStat
  • python语法-def()详细介绍(特别全)

    1 什么是函数 在 Python 中 函数是一种可重用的代码块 用于执行特定的任务或操作 函数可以接受输入参数 并返回输出结果 从而实现模块化和封装性编程的目的 Python 中定义函数的语法如下 def function name par
  • 网络安全比赛A模块任务书

    前言 这是作者这几个月来的第一次更新文章 问就是太忙了 最近要去参加国赛 在此重新回来写文章 也不知道能写多久 就当练习了 一 A模块基础设施设置 安全加固 A 1 登录加固 1 密码策略 a 最小密码长度不少于8个字符 将密码长度最小值的
  • data1

    两数之和 给定一个整数数组 nums 和一个目标值 target 请你在该数组中找出和为目标值的那 两个 整数 并返回他们的数组下标 你可以假设每种输入只会对应一个答案 但是 你不能重复利用这个数组中同样的元素 给定 nums 2 7 11
  • vue3+ts预览和下载word,pdf,excel

    文章目录 前言 一 vue office相比其他库的优势 二 使用步骤 1 引入库 2 组件封装 3 组件使用 总结 前言 最近项目一直在做一些文档方面的相关操作 例如查看文件 做文件导出 一般的导出格式为word excel pdf 等
  • STM32 实战中的一些技术问题解决

    开发板高速USB接口延迟问题 首先是检查硬件接口布线和插槽整体有无损坏 第二是发送数据包进行测试 判断是哪种数据类型和字段会发生时延 然后对症解决问题 以上两种方式能够解决80 的延迟问题 当然 也有比较少见的疑难杂症 发现当 USB 线拔
  • P1182 数列分段 Section II

    题目描述 对于给定的一个长度为N的正整数数列 A 现要将其分成 M M N 段 并要求每段连续 且每段和的最大值最小 关于最大值最小 例如一数列 4 2 4 5 1 要分成 3 段 将其如下分段 4 2 4 5 1 第 1 段和为 6 第
  • ubuntu18.04安装显卡驱动(四种方式)

    一 引言 安装ubuntu显卡驱动根据经验来看一共有四种方法 推荐使用方法三和方法四最简单快捷 一般方法三就可以解决 方法三不可以的话再用其他办法 反正自己多试试 大不了就重装系统嘛 还有一个新系统先别配置其他东西 先安显卡驱动 根据实验室
  • stm32定时器部分 产生spwm波

    用的是野火的例程 main函数 define CLI set PRIMASK 1 define SEI set PRIMASK 0 int main void CLI SEI TIM34 PWM Init while 1 bsp pwm o
  • ICP算法思想与推导详解——什么东西“最近点”,又“迭代”了什么?

    一 什么是ICP ICP的全称是 iterative closest point 迭代最近点 它是一种点云匹配的算法 在三维重建或者视觉Slam场景中 经常需要确定某一时刻的相机位姿 相机在运动过程中 不同时刻对同一物体获取的三维点云信息是