点击上方“3D视觉工坊”,选择“星标”

干货第一时间送达

作者:于凡

https://zhuanlan.zhihu.com/p/96908474

本文转载自知乎,作者已授权,未经许可请勿二次转载。

迭代最近点算法ICP(Iterative Closest Point)

问题描述

假设我们有两组点集,注意这里的 P和Q 分别相对于变换前和变换后的相机参考系。我们要解决的问题是找一组 R 和 T ,使得$\mathbf{P}$中的每一个点经过变化后同 Q 中的最近点的误差之和最小。用数学的话描述就是最小化如下一个目标函数:  求解的方法有很多,这里只介绍SVD方法

目标函数简化

我们定义两组点集的中心为

  注意到最后一项

从而原式可化简为

其中 该目标函数的最优解求解可以分为两部分,先求第一项,再求第二项(实际上第二项最优解始终为0)

即最小化目标函数等价于最大化

SVD求解

在上一步的基础上,有

引理1:对任意正定对称阵$AA^T$和任意正交阵$B$,有

 这个引理用Schwarz不等式很容易得到,不在这里证明了。我们的目的是什么呢?根据(1.5),我们的目的是要找一个R使得Tr(RH)最大。那由上面这个引理,我们很容易想到,如果RH是一个对称正定的形式,那对任何旋转矩阵R,显然迹只会不增。因此我们对H做SVD分解, ,那么 就是我们要找的R。因为

是正定对称阵,则由引理1可知,对任意旋转矩阵(正交)B,都有

即X是使得(1.5)式最大的R。

迭代过程

实际上刚才我们只完成了一次计算,而ICP的全称是Iterative Closest Point,即迭代最近点。我们来理解一下整个过程

1.对P中的每个点,在Q中找到匹配的最近点。这里需要注意,并不是每次的点云都是一一匹配,点云的数量是一方面,另外可以预见的是,很容易出现多对一最近点匹配,当然,可以通过一些额外的限定在达到一对一匹配的效果。

2.根据上述过程计算最优的R和T.

3.利用得到的位姿作用于P,如果此时的误差大于阈值,则重新进行迭代,直到迭代次数达到阈值或者误差小于阈值。

简单的理解,有点像梯度下降寻找极值点的过程,同样的,一个好的初值对加快ICP的收敛过程也十分重要。另外点对点的计算量十分大,复杂度为$O(mn)$,在一维的情况下,二分查找是常见的优化,对高维的情况,一个类似的过程是通过KD树来实现的。

KD树优化匹配过程

KD树原理

KD树是每个节点均为K维数值的二叉树,其上的每个节点代表一个超平面,该超平面垂直于当前划分维度的坐标轴,并在该维度上将空间一分为二。其构建过程是循环选取数据点的各个维度来作为切分维度,将当前维度的中值作为划分点,递归处理各子树,直到所有数据点挂载完毕。

KD树的一些优化

切分维度选择的时候,一般优先选择方差大的维度开始切分。选择中值时,对数据量较大的维度,不一定严格取中值,可以随机采样一定的数据,并取采样的中值作为划分点,加快划分过程。

一个例子

以二维平面点(x,y)的集合(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)为例结合下图来说明k-d tree的构建过程。

对应的是将一个二维平面逐步划分的过程

KD树最近邻搜索过程

我们构建KD树的目的是为了加快最近点搜索过程,那么KD树如何进行最近邻搜索呢?假设我们要搜索同(3,5)最近的点。1)从根节点(7,2)出发,将当前的最近邻设为(7,2),对KD树做深度优先遍历。以(3,5)为圆心,到(7,2 )的距离为半径画圆。对在圆外的点,如果位于左侧,则忽略左子树,位于右侧,则忽略右子树。下图忽略(8,1)的右子树。2)深度遍历子节点。以(5,4)为根节点,判断(5,4)比(7,2)更近,更换最近点,并重新剪枝。此时,(7,2)的右子树均被忽略。3)深度遍历子节点,直到遍历结束,返回最近点。

完整伪代码如下图

KD树构建的复杂度为O(log(m)),查找的复杂度为O(mlog(n)),所以利用KD查找最近邻的复杂度为O(mlog(n)),远小于O(mn)。

正态分布变换NDT(Normal Distribution Transform)

简介

目前的配准方法,前提都是环境大部分是不变的,但是完全不变的环境其实也是很少的,比如一辆车飞驰而过,一个人走过等。我们更多应该考虑的是允许小部分差异的配准,这时候点对点匹配比如ICP就会出现一些问题,而NDT则可以很好地解决细微差。我们知道,如果随机变量满足正态分布,那么对应的概率密度函数(PDF)为

对随机向量则有

其中D表示维数, 表示协方差矩阵。简单来说,一维的数变成了高维的向量。

目标函数

与ICP不同,NDT假设点云服从正态分布,我们的目的是找一个姿态,使得当前扫描点位于参考扫描平面上的可能性最大。假设当前扫描得到的点云为 ,用空间转换函数 来表示使用姿态变换 来移动 。我们的目标是最大化似然函数: 

等价于最小化负对数似然,这么做还有一个好处,加法对求导更友好

基本步骤

在上一部分中我们没有解释p函数,当然你可能会说不就是概率密度函数吗?是,但是我们并没有先验的概率密度函数,怎么得到的。这里唯一可以利用的即使参考点云,我们将参考点云网格化,然后计算每个网格的多维正态分布参数。用 表示一个网格内的所有扫描点,则

均值:

协方差矩阵:

概率密度函数:

实际上这里f不是正态分布也可以 下一步就是如何求解

对目标函数进行数学上的简化

如下图所示,直接取负对数会出现无穷大的点,这样偶然扫到的一些异常点可能会对本来表现很好的结果产生很大的影响导致被舍弃,为了避免这种情况,在原函数的基础上做了一些限制。

这时候我们的目标函数中的单项就变成

我们之前也提到了,加法对求导比较友好,但是log函数对求导不友好,而在求解优化问题的时候,经常会利用到一阶二阶导数(比如梯度下降,牛顿法),所以我们想办法对上述函数做一个近似,如果你对函数图像有一定的敏感性的化,很容易发现上面这两个绿色的函数好像还挺像?也就是说我们可以利用高斯函数来拟合负对数

利用x=0, 解得近似参数为

这样,我们可以得到不同项对NDT结果的贡献(偏移项是一致的,可暂时忽略),注意这里多了一个负号,我的理解应该是为了之后求导时前面的负号正好可以消掉

原目标函数变成

牛顿法求解

这公式实在长,直接截图了,牛顿法的关键就是通过梯度矩阵g和海森矩阵H求解步长

这里对上面的结果求导可得

举一个简单的二维的例子来说明上面的$x_k$对$p_i$的求导过程

最后结合流程图梳理一下NDT的流程

1)划分网格

2)计算各网格的PDF

3)对每个点云数据,找到对应的网格点,并根据PDF和评分函数计算结果

4)根据结果更新g和H,计算新的步长

5)判断是否收敛或达到迭代次数,是则跳出,否则继续步骤3-5

对NDT实验结果的一些优化

1.cell size. 太大了容易导致损失一些局部特征,太小了则会增加很多计算量,太小会导致失去统计普适性,部分数据对结果影响过大。另外,作者直接舍弃掉少于五个数据的网格(因为会造成协方差矩阵不可逆)。

2.Fixed discretization。固定大小是最常见的划分方式,操作简单,而且容易找到每个点对应的网格。缺点的话见底下几种方法

3.Octree discretization。如何快速找到每个点对应的网格是搜索速度的关键,八叉树结构是常见的三维搜索树。

4.Iterative discretization。好的初始位置可以加快收敛过程,一个常见的方法就是起始位置迭代,将上一次的终点位姿作为本次的起点位姿

5.Adaptive clustering。非固定大小网格划分的一种方法,采用K均值聚类(其他聚类方式类似)划分,更能表现出每个局部数据的特征。

6.Linked cells。上面提到数据少于五的网格会被舍弃,导致会出现一些空网格,损失了一些完整性,一个改进措施是将这些空网格用指针连接到最近的非空网格上,以该处的PDF代替,由于处于边缘,值还是很小,但是保证了数据的完整性。

7.Trilinear interpolation。插值的逻辑就是固定划分实际上会出现边缘不连续的情况,插值法相当于做了一个平滑,计算的时候考虑所有含该数据点的网格取最优值,计算量大约是原来的4倍,但效果也有较大的改善。示意图如下

其他一些配准方法

1.Iterative dual correspondences (IDC) algorithm。ICP的一种改进,主要是采用极坐标代替笛卡尔坐标系进行最近点搜索

2.Probabilistic iterative correspondence (PIC) method。这个方法考虑了噪声和初始位姿的不确定性

3.Gaussian fields。采用高斯混合模型,类似NDT

4.Conditional random fields (CRFs) 。条件随机场,还没细看

5.Branch-and-bound strategy 。分支定界法,没看。

6.Registration using local geometric features。结合图像的局部特征进行匹配

7.除此之外最近还有一些结合深度学习的方法,比如百度无人车团队2019CVPR的工作:L3-Net: Towards Learning based LiDAR Localization for Autonomous Driving。输入包括实时激光点云,地图和IMU数据,输出位姿结果。

推荐阅读:

吐血整理|3D视觉系统化学习路线

那些精贵的3D视觉系统学习资源总结(附书籍、网址与视频教程)

超全的3D视觉数据集汇总

大盘点|6D姿态估计算法汇总(上)

大盘点|6D姿态估计算法汇总(下)

机器人抓取汇总|涉及目标检测、分割、姿态识别、抓取点检测、路径规划

汇总|3D点云目标检测算法

汇总|3D人脸重建算法

那些年,我们一起刷过的计算机视觉比赛

总结|深度学习实现缺陷检测

深度学习在3-D环境重建中的应用

汇总|医学图像分析领域论文

大盘点|OCR算法汇总

重磅!3DCVer-学术论文写作投稿 交流群已成立

扫码添加小助手微信,可申请加入3D视觉工坊-学术论文写作与投稿 微信交流群,旨在交流顶会(ICRA/IROS/ROBIO/CVPR/ICCV/ECCV等)、顶刊(IJCV/TPAMI/TIP等)、SCI、EI等写作与投稿事宜。

同时也可申请加入我们的细分方向交流群,目前主要有3D视觉CV&深度学习SLAM三维重建点云后处理自动驾驶、CV入门、三维测量、VR/AR、3D人脸识别、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别、硬件选型、学术交流、求职交流等微信群,请扫描下面微信号加群,备注:”研究方向+学校/公司+昵称“,例如:”3D视觉 + 上海交大 + 静静“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进去相关微信群。原创投稿也请联系。

▲长按加微信群或投稿

▲长按关注公众号

3D视觉从入门到精通知识星球:针对3D视觉领域的知识点汇总、入门进阶学习路线、最新paper分享、疑问解答四个方面进行深耕,更有各类大厂的算法工程人员进行技术指导。与此同时,星球将联合知名企业发布3D视觉相关算法开发岗位以及项目对接信息,打造成集技术与就业为一体的铁杆粉丝聚集区,近1000+星球成员为创造更好的AI世界共同进步,知识星球入口:

学习3D视觉核心技术,扫描查看介绍,3天内无条件退款

圈里有高质量教程资料、可答疑解惑、助你高效解决问题

两种常见的点云配准方法ICPNDT相关推荐

  1. GICP:基于体素泛化ICP方式的准确快速点云配准方法

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 标题: Voxelized GICP for Fast and Accurate 3D Point C ...

  2. KSS-ICP: 基于形状分析技术的点云配准方法

    目录 1. 概述 2. 算法实现 3. 实验结果 总结 Reference 三维点云配准是三维视觉领域一个经典问题,涉及三维重建,定位,SLAM等具体应用问题.传统的配准可以被分为两条技术路线,即基于 ...

  3. android内存池,两种常见的内存管理方法:堆和内存池

    描述 本文导读 在程序运行过程中,可能产生一些数据,例如,串口接收的数据,ADC采集的数据.若需将数据存储在内存中,以便进一步运算.处理,则应为其分配合适的内存空间,数据处理完毕后,再释放相应的内存空 ...

  4. 使用定制的NSDictionary的方法,对NSArray进行排序(附:数组排序两种常见方法)

    NSArray中存放的是NSDictionary,可以使用策略的方法对NSDictionary进行定制,增加比较的方法.然后调用NSArray的sortUsingSelector方法对数组进行排序,这 ...

  5. 景联文科技|两种常见的视频标注方法

    随着人工智能的迅速发展,数据标注行业也迎来了高速发展,视频数据标注是一种用机器自动生成自然语言文字来描述视频内容的过程,它在视觉和文字之间起到非常重要的连接作用,同时针对不同的应用场景,也衍生出了不同 ...

  6. 两种常见的内存管理方法:堆和内存池

    在程序运行过程中,可能产生一些数据,例如,串口接收的数据,ADC采集的数据.若需将数据存储在内存中,以便进一步运算.处理,则应为其分配合适的内存空间,数据处理完毕后,再释放相应的内存空间.为了便于内存 ...

  7. CSS初始化的两种常见方法

    CSS初始化的两种常见方法 两种CSS初始化的常见方案,都是通用类的 CSS reset Eric Meyer写的 CSS reset,源码不是很长: /* http://meyerweb.com/e ...

  8. 十六进制的转换为十进制两种常见方法

    十六进制的转换为十进制两种常见方法 好久以前学的都忘了,正好复习一下 对于十六进制转十进制 第一种:快速法(自己挺喜欢第一种的快捷) 比如: 012A=0 X 163 + 1 X 162+ 2 X 1 ...

  9. 针对地图可压缩性的点云配准方法评估(IROS 2021)

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨Penny@知乎 来源丨https://zhuanlan.zhihu.com/p/2009241 ...

最新文章

  1. Solaris下访问windows共享资源
  2. 人工智能、核聚变、碳捕捉……最有可能帮助拯救地球的10项技术
  3. 如何在JavaScript / jQuery中查找数组是否包含特定字符串? [重复]
  4. 【吾日三省吾身】2015.6.03-涅槃行动第十六天
  5. Azure DevOps Server CI - 自搭跨平台容器代理Agents
  6. Qt调用CUDA动态库及配置
  7. jquery砸金蛋 高仿阿里旅游砸金蛋
  8. 创建自己的uboot-基于IMX6
  9. Tensorflow2.0学习(八) — tf.dataset自定义图像数据集
  10. ARM指令集和X86指令集对比
  11. jlinkV8驱动里面找不到gd32f130c8t6芯片怎么办?keil下载时候报错 dll错误,我刚才找到问题的原因了。就是jlink驱动版本太低,用6.88c就可以了 ,以下是我获得解答链接感谢
  12. matlab图片处理基本知识,Matlab图像处理基础知识
  13. python - 例题分析:工时与工资
  14. matlab解符号高次方程,matlab解高次方程的问题
  15. word中如何去掉文档右侧带格式的批注框
  16. OnInit和OnLoad
  17. 腾讯云服务器配置code-server
  18. 计算机二级office公式汇总,计算机二级Office2010Eexcel公式汇总
  19. Bubba 迷你效劳器
  20. [Unity] GPU动画实现(三)——材质合并

热门文章

  1. activity生命周期及数据保存
  2. 10款在线格式转化应用
  3. 谈谈架构的本质和架构分类
  4. 34岁,外企倒闭成功上岸大厂,50K,附面试秘籍
  5. CTO怒了:“如果中台不省钱,我建个屁中台啊!”
  6. 程序员网购18年不拆快递!意外离世后满屋快递被拆开,价值3500万!
  7. 震精!Spring Boot内存泄露,排查竟这么难!
  8. 讲解 Redis 的一篇深度好文!
  9. 又来搞事情了,这次女友让我研究如何实现一个文件系统
  10. 饿了么交付中心语言栈转型总结