惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

爱范儿
爱范儿
Security Latest
Security Latest
NISL@THU
NISL@THU
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
C
Cybersecurity and Infrastructure Security Agency CISA
Cloudbric
Cloudbric
T
Threat Research - Cisco Blogs
大猫的无限游戏
大猫的无限游戏
C
CXSECURITY Database RSS Feed - CXSecurity.com
阮一峰的网络日志
阮一峰的网络日志
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
雷峰网
雷峰网
C
Cisco Blogs
V
Vulnerabilities – Threatpost
S
Security Archives - TechRepublic
V
Visual Studio Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
J
Java Code Geeks
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Know Your Adversary
Know Your Adversary
博客园 - 叶小钗
腾讯CDC
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Privacy International News Feed
P
Palo Alto Networks Blog
博客园_首页
V
V2EX
WordPress大学
WordPress大学
Schneier on Security
Schneier on Security
月光博客
月光博客
博客园 - 司徒正美
Google DeepMind News
Google DeepMind News
TaoSecurity Blog
TaoSecurity Blog
博客园 - 聂微东
酷 壳 – CoolShell
酷 壳 – CoolShell
人人都是产品经理
人人都是产品经理
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 【当耐特】
The Cloudflare Blog
罗磊的独立博客
美团技术团队
N
News | PayPal Newsroom
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Last Week in AI
Last Week in AI
K
Kaspersky official blog
Google Online Security Blog
Google Online Security Blog
S
SegmentFault 最新的问题
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Tailwind CSS Blog

又见苍岚

COLMAP PatchMatch Stereo 算法详解 事件驱动的状态机框架:从理论到工程实践 Git 在国内网络环境下无法 Push 的排查与修复 —— 配置 Clash 代理 分段五次多项式插值原理详解 路径插值方法深度对比研究 Claude Code 使用指南 OpenClaw 记忆管理与技能创建指南 CBS(Conflict-Based Search)算法详解 A* 算法及其变种详解 OpenClaw 配置多 Agents Windows Powershell 无法加载文件,因为在此系统上禁止运行脚本问题的解决方案 MaxClaw 安装流程 大模型 AI 名词介绍 AList 网盘聚合工具简介 Protobuf 简介与测试 Claude Code 简介以及 GLM 4.7 模型接入 Github 歌词下载工具 163MusicLyrics Python __getattr__ 懒加载 Python TypedDict 机器人仿真平台 Gazebo 安装记录 机器人仿真平台 Gazebo 简介 多机器人路径规划问题(Multi-Agent Path Finding, MAPF)简介 Python exifread 读取修改过的 jpeg 信息错误问题修复 3D 坐标系变换的理解 3D 旋转矩阵基本概念 MongoDB Compass 介绍 Python 环境管理工具 uv Flutter 开发指南 Snipaste 安装下载与黑屏问题解决方案 全局路径规划算法记录 2025 Python 版本性能测试 Flutter Hello World Flutter 安装环境配置 Ubuntu VMware 硬盘扩容后 SMBus Host controller not enabled 报错问题解决 Python NetworkX 教程 Docker GPU 报错 - Failed to initialize NVML Unknown Error 解决方案 Python matplotlib 图表绘制 cuda-toolkit 安装替代 Cuda 与 Cudnn Jinja2 Python 利用 docxtpl 和 Jinja2 生成基于模板的 Word 文档 Docker 实现 CPU 核心隔离 LoFTR 基于 Transformer 的特征提取匹配算法 OmniGlue 特征匹配 SuperGlue 使用图神经网络学习特征匹配 Ubuntu 下将 xlsx 文件按照 sheet 转换为 图片 Python 使用 SQLAlchemy Python FastAPI 教程 openwrt 软路由配置安装 Nav2 地图文件(PGM/YAML)规范标准 3D OBJ 模型转换为 glb 瓦片格式 Python 源码 Redis 数据库介绍 Ubuntu 22.04 内核自动升级导致 MongoDB 7.0.12 错误记录 ubuntu 20.04 安装 ROS Noetic ubuntu 18.04 安装 ROS Melodic VMware Workstation Pro 个人免费版下载、安装、使用指南 Hybrid A-star 路径规划 Reeds-Shepp 曲线 Dubins 曲线 Linux kvm 虚拟机网络不通的问题解决方法 Ubuntu 自动内存清理 BiliBili 缓存视频转 mp4 Python 求解线性规划 3D Gaussian Splatting 官方源码实践记录 ImageMagick 教程 Ubuntu 22.04 安装 Colmap 对数几率 odds Ubuntu nmcli 网络管理工具使用指南 SuperPoint 自监督深度学习特征点提取 SyncTV Music Tag Web 在线音乐信息整理工具 ncm 格式转 mp3 MusicBrainz 音乐元数据百科数据库 Ubuntu 网络流量监控工具 私人云音乐平台 Navidrome 入门 手眼标定 四元数(Quaternions) OHTTPS 实现免费自动 https 证书申请、更新、部署 ubuntu 22.04 安装 CloudCompare 单机 KVM 虚拟机冷迁移 Ubuntu 22.04 使用 mdadm 实现软 raid 小鱼 一键安装 ROS-humble Fluid -46- 基于 Simpletex API 构建公式识别页面 公式识别 API 简介 -- Simpletex 使用 Python web 部署库 waitress 3D Gaussian Splatting for Real-Time Radiance Field Rendering Ubuntu Swap 简介与空间扩展 Ubuntu 24.04 安装 forticlient Clash Verge 使用 MongoDB 7.0.17 集群 Docker 构建源码 Error code - 2013. Lost connection to MySQL server during query 问题解决 Python 日志记录库 loguru 使用指北 Python 实现 Web 日志查看服务 MySQL LOAD DATA LOCAL INFILE 极速数据加载 Image size exceeds limit of 89478485 pixels 解决方案 Docker 使用 NVIDIA GPU 驱动错误解决 阿里云 docker 镜像仓库 Ubuntu中没有wired connected的解决方案 MinIO 简介 subconverter 代理订阅格式转换 修复 node –openssl-legacy-provider is not allowed in NODE_OPTIONS 错误
三维点云配准 -- ICP 算法
Yiwei Zhang · 2024-10-10 · via 又见苍岚

ICP (Iterative Closest Point) 算法是基于 EM(Expectation-maximization algorithm)思想的方法,采用交替迭代法优化得到最优值,本文记录相关内容。

问题描述

点云配准(Point Cloud Registration)指的是输入两幅点云 $𝑃_𝑠$ (source) 和 $𝑃_𝑡$ (target) ,输出一个变换 $𝑇$ 使得 $𝑇(𝑃_𝑠)$ 和 $𝑃_𝑡$ 的重合程度尽可能高。变换 $𝑇$ 可以是刚性的(rigid),也可以不是,本文下面只考虑刚性变换,即变换只包括旋转、平移。

点云配准可以分为粗配准(Coarse Registration)和精配准(Fine Registration)两步。粗配准指的是在两幅点云之间的变换完全未知的情况下进行较为粗糙的配准,目的主要是为精配准提供较好的变换初值;精配准则是给定一个初始变换,进一步优化得到更精确的变换。

图像配准是图像处理研究领域中的一个典型问题和技术难点,其目的在于比较或融合针对同一对象在不同条件下获取的图像,例如图像会来自不同的采集设备,取自不同的时间,不同的拍摄视角等等,有时也需要用到针对不同对象的图像配准问题。具体地说,对于一组图像数据集中的两幅图像,通过寻找一种空间变换把一幅图像映射到另一幅图像,使得两图中对应于空间同一位置的点一一对应起来,从而达到信息融合的目的。 一个经典的应用是场景的重建,比如说一张茶几上摆了很多杯具,用深度摄像机进行场景的扫描,通常不可能通过一次采集就将场景中的物体全部扫描完成,只能是获取场景不同角度的点云,然后将这些点云融合在一起,获得一个完整的场景。

常用方法

  1. ICP

    缺点:

    1
    2
    3
    A.要剔除不合适的点对(点对距离过大、包含边界点的点对)
    B.基于点对的配准,并没有包含局部形状的信息
    C.每次迭代都要搜索最近点,计算代价高昂

    存在多种优化了的变体算法,如八叉树等

  2. IDC

    1
    ICP的一种改进,采用极坐标代替笛卡尔坐标进行最近点搜索匹配
  3. PIC

    1
    考虑了点云的噪音和初始位置的不确定性
  4. Point-based probabilistic registration

    1
    需要首先建立深度图的三角面片
  5. NDT——正态分布变换:

    1
    2
    计算正态分布是一个一次性的工作(初始化),不需要消耗大量代价计算最近邻搜索匹配点   
    概率密度函数在两幅图像采集之间的时间可以离线计算出来
  6. Gaussian fields

    1
    和NDT正态分布变换类似,利用高斯混合模型考察点和点的距离和点周围表面的相似性
  7. Quadratic patches

  8. Likelihood-field matching——随机场匹配

  9. CRF匹配

    1
    缺点: 运行速度慢,在3d中实时性能不好,误差大。
  10. Branch-and-bound registration

  11. Registration using local geometric features

ICP

目前应用最广泛的点云精配准算法是迭代最近点算法(Iterative Closest Point, ICP)及各种变种 ICP 算法。ICP 算法是一种点集对点集配准方法。如下图所示,PR(红色点云)和RB(蓝色点云)是两个点集,该算法就是计算怎么把PB平移旋转,使PB和PR尽量重叠。

ICP算法本质上是基于最小二乘法的最优配准方法。该算法重复进行选择对应关系点对, 计算最优刚体变换,直到满足正确配准的收敛精度要求。算法的目的是要找到待配准点云数据与参考云数据之间的旋转参数R和平移参数 T,使得两点数据之间满足某种度量准则下的最优匹配。

ICP 算法描述

对于 $𝑇$ 是刚性变换的情形,点云配准问题可以描述为:

$$ \begin{equation} R^{\ast}, t^{\ast} = \mathop{\arg\min}_{R, t} \frac{1}{|P_s|} \sum_{i=1}^{|P_s|} || p_t^i - (R \cdot p_s^i + t) ||^2 \end{equation} $$

这里 $𝑝_𝑠$ 和 $p_t$ 是源点云和目标点云中的一一对应点。

ICP 算法的直观想法如下:

  • 如果我们知道两幅点云上点的对应关系,那么我们可以用 Least Squares 来求解 R, t 参数;
  • 怎么知道点的对应关系呢?如果我们已经知道了一个大概靠谱的 R, t 参数,那么我们可以通过贪心的方式找两幅点云上点的对应关系(直接找距离最近的点作为对应点)。

ICP 算法实际上就是交替进行上述两个步骤,迭代进行计算,直到收敛。

ICP 一般算法流程为:

  1. 点云预处理
    • 滤波、清理数据等
  2. 匹配
    • 应用上一步求解出的变换,找最近点
  3. 加权
    • 调整一些对应点对的权重
  4. 剔除不合理的对应点对
  5. 计算 loss
  6. 最小化 loss,求解当前最优变换
  7. 回到步骤 2. 进行迭代,直到收敛

整体上来看,ICP 把点云配准问题拆分成了两个子问题:

  • 找最近点
  • 找最优变换

找最近对应点(Find Closet Point)

利用初始 $R_0$、$𝑡_0$ 或上一次迭代得到的 $R_{k−1}$、$t_{k−1}$ 对初始点云进行变换,得到一个临时的变换点云,然后用这个点云和目标点云进行比较,找出源点云中每一个点在目标点云中的最近邻点。

如果直接进行比较找最近邻点,需要进行两重循环,计算复杂度为 $O(|P_s|⋅|P_t|) $,这一步会比较耗时,常见的加速方法有:

  • 设置距离阈值,当点与点距离小于一定阈值就认为找到了对应点,不用遍历完整个点集;
  • 使用 ANN(Approximate Nearest Neighbor) 加速查找,常用的有 KD-tree;KD-tree 建树的计算复杂度为 O(N log(N)),查找通常复杂度为 O(log(N))(最坏情况下 O(N))。

求解最优变换(Find Best Transform)

对于 point-to-point ICP 问题,求最优变换是有闭形式解(closed-form solution)的,可以借助 SVD 分解来计算。

先给出结论,在已知点的对应关系的情况下,设 $\bar p_s$, $\bar p_t$ 分别表示源点云和目标点云的质心,令 $\hat p_s^i = p_s^i - \bar p_s$,$\hat p_t^i = p_t^i - \bar p_t$ ,令:

$$ H = \sum_{i=1}^{|P_s|} {\hat p_s^i} {\hat p_t^i}^T $$ 这是一个 $3 \times3$ 矩阵,对 H 进行 SVD 分解得到 $H = U \Sigma V^T$ ,则 point-to-point ICP 问题最优旋转为: $$ \begin{equation} R^{\ast} = V U^T \end{equation} $$ 最优平移为: $$ \begin{equation} t^{\ast} = \bar p_t - R^{\ast} \bar p_s \end{equation} $$ 下面分别给出证明。

计算最优平移

令 $N = |P_s|$ ,设 $F(t) = \sum_{i=1}^{N} ||(R \cdot p_s^i + t) - p_t^i||^2$ ,对其进行求导,则有: $$ \begin{equation} \begin{aligned} \frac{\partial F}{\partial t} &= \sum_{i=1}^{N} 2 (R \cdot p_s^i + t - p_t^i) \\ &= 2nt + 2R\sum_{i=1}^{N}p_s^i - 2\sum_{i=1}^{N}p_t^i \end{aligned} \end{equation} $$ 令导数为 0 ,则有: $$ \begin{equation} \begin{aligned} t &= \frac{1}{N} \sum_{i=1}^{N} p_t^i - R \frac{1}{N} \sum_{i=1}^{N} p_s^i \\ &= \bar p_t - R \bar p_s \end{aligned} \end{equation} $$

无论 R 取值如何,根据上式我们都可以求得最优的 t,使得 loss 最小。下面我们来推导最优旋转的计算公式。

计算最优旋转

经过最优平移的推导,我们知道无论旋转如何取值,都可以通过计算点云的质心来得到最优平移,为了下面计算上的简便,我们不妨不考虑平移的影响,先将源点云和目标点云都转换到质心坐标下,这也就是之前令 $\hat p_s^i = p_s^i - \bar p_s$ , $\hat p_t^i = p_t^i - \bar p_t$ 的意义。

下面我们用 $\hat p_s^i$ 和 $\hat p_t^i$ 进行推导。

不考虑平移,则 loss 可以写成:

$$ \begin{equation} F(R) = \sum_{i=1}^{N} ||R \cdot \hat p_s^i - \hat p_t^i||^2 \end{equation} $$ 先化简 $||R \cdot \hat p_s^i - \hat p_t^i||^2$: $$ \begin{equation} \begin{aligned} ||R \cdot \hat p_s^i - \hat p_t^i||^2 &= (R \cdot \hat p_s^i - \hat p_t^i)^T(R \cdot \hat p_s^i - \hat p_t^i) \\ &= ({\hat p_s^i}^T R^T - {\hat p_t^i}^T)(R \cdot \hat p_s^i - \hat p_t^i) \\ &= {\hat p_s^i}^T R^T R {\hat p_s^i} - {\hat p_t^i}^T R {\hat p_s^i} - {\hat p_s^i}^T R^T {\hat p_t^i} + {\hat p_t^i}^T {\hat p_t^i} \\ &= ||{\hat p_s^i}||^2 + ||{\hat p_t^i}||^2 - {\hat p_t^i}^T R {\hat p_s^i} - {\hat p_s^i}^T R^T {\hat p_t^i} \\ &= ||{\hat p_s^i}||^2 + ||{\hat p_t^i}||^2 - 2{\hat p_t^i}^T R {\hat p_s^i} \end{aligned} \end{equation} $$

这里利用到了 $R^T R = I$ 和 ${\hat p_t^i}^T R {\hat p_s^i} = {\hat p_s^i}^T R^T {\hat p_t^i}$ (标量的转置等于自身)的性质。

由于点的坐标是确定的(和 R 无关),所以最小化原 loss 等价于求:

$$ \begin{equation} R^{\ast} = \mathop{\arg\min}_{R} (-2 \sum_{i=1}^{N} {\hat p_t^i}^T R {\hat p_s^i}) \end{equation} $$ 也即为求: $$ \begin{equation} R^{\ast} = \mathop{\arg\max}_{R} (\sum_{i=1}^{N} {\hat p_t^i}^T R {\hat p_s^i}) \end{equation} $$ 注意到 $\sum_{i=1}^{N} {\hat p_t^i}^T R {\hat p_s^i} = trace(P_t^T R P_s)$ (由矩阵乘法及 trace 的定义可得) 则问题转化为: $$ \begin{equation} R^{\ast} = \mathop{\arg\max}_{R} trace(P_t^T R P_s) \end{equation} $$ 根据 trace 的性质 $trace(AB)=trace(BA)$,(这里不要求 A, B 为方阵,只要 $A*B$ 是方阵即可),有: $$ \begin{equation} trace(P_t^T R P_s) = trace(R P_s P_t^T) \end{equation} $$ 还记得前面定义的矩阵 H 和其 SVD 分解吗?带入上式得到: $$ \begin{equation} \begin{aligned} trace(P_t^T R P_s) &= trace(R P_s P_t^T) \\ &= trace(R H) \\ &= trace(R U \Sigma V^T) \\ &= trace(\Sigma V^T R U) \end{aligned} \end{equation} $$ 注意这里 $𝑉,𝑈,𝑅$ 都是正交矩阵(orthogonal matrices),所以 $V^T R U$ 也是正交矩阵。令 $$ M = V^T R U = \left[ \begin{array}{cccc} m_{11} & m_{12} & m_{13} \\ m_{21} & m_{22} & m_{23} \\ m_{31} & m_{32} & m_{33} \end{array} \right] $$ 则有: $$ \begin{equation} \begin{aligned} trace(\Sigma V^T R U) &= trace(\Sigma M) \\ & = \sigma_1 m_{11} + \sigma_2 m_{22} + \sigma_1 m_{33} \end{aligned} \end{equation} $$ 根据奇异值非负的性质和正交矩阵的性质(正交矩阵中的元素绝对值不大于 1),容易证得只有当 𝑀 为单位阵时 $trace(ΣM)$ 最大,即: $$ \begin{equation} \begin{aligned} V^T R U = I \\ R = V U^T \end{aligned} \end{equation} $$ 所以有 $R^{\ast} = V U^T$。 最后还需要进行 Orientation rectification,即验证 $R^{\ast} = V U^T$ 是不是一个旋转矩阵(检查是否有 $|R|=1$),因为存在 $|R|=−1$ 的可能,此时 $𝑅$ 表示的不是旋转而是一个 reflection,所以我们还要给上述优化求解加上一个 $|R|=1$ 的约束。 根据矩阵行列式的性质,以及 $U, V$ 都是正交阵: $$ \begin{equation} \begin{aligned} |M| &= |V^T| |U| |R| \\ &= |V^T| |U| = \pm 1 \end{aligned} \end{equation} $$

如果 $|VU^T|=1$,则 $|M|=1$, $R∗=VUT$ 已经给出最优旋转;如果 $|VU^T|=−1$,则 $|M|=−1$,我们需要求解此时的 $𝑅$,也就是分析 $M$ 应该具有何种形式。具体的讨论请参考这里,本文直接给出结论:当 $|M|=−1$ 时,使得 $𝑡𝑟𝑎𝑐𝑒(Σ𝑀) $ 最大的 $𝑀$ 为:

$$ \begin{equation} M = \left[ \begin{array}{cccc} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & -1 \end{array} \right] \end{equation} $$ 综合考虑 $|M|=1$ 和 $|M|=−1$ 两种情况,我们可以得到: $$ \begin{equation} R^{\ast} = V \left[ \begin{array}{cccc} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & |V U^T| \end{array} \right] U^T \end{equation} $$

简单总结一下求解最优变换的步骤:

  1. 计算源点云和目标点云质心;
  2. 将源点云和目标点云转换到质心坐标系;
  3. 计算矩阵 H(形式类似“协方差矩阵”);
  4. 对 H 求 SVD 分解,根据公式求得 $𝑅^∗$;
  5. 根据公式计算 $𝑡^∗$。
迭代

每一次迭代我们都会得到当前的最优变换参数 $R_k,t_k$ ,然后将该变换作用于当前源点云;“找最近对应点”和“求解最优变换”这两步不停迭代进行,直到满足迭代终止条件,常用的终止条件有:

  • $R_k,t_k$ 的变化量小于一定值
  • loss 变化量小于一定值
  • 达到最大迭代次数

ICP 的优缺点及一些改进算法

ICP 优点:

  • 简单,不必对点云进行分割和特征提取
  • 初值较好情况下,精度和收敛性都不错

ICP 缺点:

  • 找最近对应点的计算开销较大
  • 只考虑了点与点距离,缺少对点云结构信息的利用

原始的 ICP 算法计算开销大,对初始变换敏感,容易陷入局部最优解。自 ICP 提出以来,有相当多的 ICP 改进算法,简要列举一些:

  • Point-to-Plane ICP,原始 ICP 算法的代价函数中使用的 point-to-point 距离,point-to-plane 则是考虑源顶点到目标顶点所在面的距离,比起直接计算点到点距离,考虑了点云的局部结构,精度更高,不容易陷入局部最优;但要注意 point-to-plane 的优化是一个非线性问题,速度比较慢,一般使用其线性化近似;
  • Plane-to-Plane ICP,point-to-plane 只考虑目标点云局部结构, plane-to-plane 顾名思义就是也考虑源点云的局部结构,计算面到面的距离;
  • Generalized ICP (GICP),综合考虑 point-to-point、point-to-plane 和 plane-to-plane 策略,精度、鲁棒性都有所提高;
  • Normal Iterative Closest Point (NICP),考虑法向量和局部曲率,更进一步利用了点云的局部结构信息,其论文中实验结果比 GICP 的性能更好。

实际使用中的一些注意事项

  • ICP 比较依赖于变换初值,平移比较简单,直接用点云质心来估计;旋转初值的话可以手动调一个粗略值,或者沿每个轴的旋转进行采样、组合来尝试(不适合实时性应用);
  • 点太多的话可以先降采样;
  • 找到一些 anchor 点对(比如先用特征点匹配),可以帮助加速收敛;
  • 对应用场景引入一些合理假设,比如限制旋转、平移的范围,变换自由度数量等。

参考资料

文章链接:
https://www.zywvvd.com/notes/3d/registration/icp/