解读《视觉SLAM十四讲》,带你一步一步入门视觉SLAM—— 第 13 讲 建图

2024-06-05 17:32

本文主要是介绍解读《视觉SLAM十四讲》,带你一步一步入门视觉SLAM—— 第 13 讲 建图,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这一讲拖到现在才开始写,其中一个主要的原因是建图部分的内容,一方面比较难,另一方面它在实际的工程中应用较少,我对这方面的了解不是特别深入。

工程中很少对视觉构建的地图进行复用,其原因主要有(来自我自己的经验):

  • ① 地图的精度较低,多数难以达到导航和定位的要求;
  • ② 视觉对光线比较敏感,构建的地图难以较好复用,有时早上建图,下午定位成功率就很低;
  • ③ 地图体积大,内存占用率高。视觉slam会维护一个比较复杂的地图数据结构,而这些数据如果不加处理,实际上是很占用资源的,对比cartographor这种激光slam的地图,同样场景下只有几十兆大小,而视觉特征点地图则达到几百兆。

而目前视觉建图中应用比较多的是稠密或者半稠密建图,因为至少还可以构建我们人类可以看的场景,于是在一些增强现实的应用场景下,它获得了一定的应用。而稀疏的特征点地图多数情况下,几乎都是都看不出啥。

这一讲书中大部分的内容都是比较完整的,而且理解起来也不难,但是如果要扩宽这些内容到实际的应用中,还是很难的。

概述

在slam中我们对地图有如下一些需求:

  • ① 定位:目前关于视觉的定位主要是通过提前构建场景的三维地图,多数情况是基于特征点的三维地图,然后通过各种的搜索方法进行重定位,可以使用词袋的方式进行粗定位,然后进行局部匹配,进而求解PnP,当然方法不仅限于此,我目前正在做一种全局描述子搜索的定位方法,效果超过了词袋的方式。
  • ② 导航:导航是指机器人能够在地图中进行路径规划,在任意两个地图点之间寻找路径,然后控制自己运动到目标点的过程。这个过程需要一个可靠的环境建图,常采用稠密地图。
  • ③ 避障:是机器人在运动过程中的一个动态调整轨迹的问题,它需要对动态障碍物有一个可靠的检测。
  • ④ 重建:它是指对环境进行三维重建,这种建图偏向于给用户观看,所以它需要建立美观、舒服的场景地图,目前几乎都是采用稠密地图。在视觉slam方面场景重建的应用还是比较多的。
  • ⑤ 交互: 这是一种更偏向于和用户进行互动的应用,它不但需要构建较好的场景地图,多数情况向下还要有语义信息,需要知道场景中有哪些东西,在哪些地方,这种上层的应用目前多数还处在研究阶段,但是这将是未来一个非常好的应用。

单目稠密重建

极线搜索与块匹配
单目稠密重建部分的内容,作者提供给了一个例子通过多张单目图像重建一个稠密的地图,这个例子有一些地方还是值得注意的。

首先,这里的前后帧匹配并不是像第7章中的那样,第七章中使用的是暴力搜索匹配,对前后两张图像上提取的特征点进行描述子匹配。但是在本章中要进行的是稠密的重建,是针对的全像素重建。

例如,对于一张1024*768尺寸的图像,在进行前后帧像素值匹配时,如果已知第一帧中的某一个像素值,然后去第二帧中搜索最近的一个,这显然会耗费巨大的运算资源,而且错误的匹配会非常多,所以加速搜索和匹配是一个很重要的步骤。作者在书中采用的极线搜索的方式,根据几何关系,第一帧观测到的空间点,一定会投影到第二帧的极线上,那么只要在极线附近搜索,势必会减少很多运算量,而且正确的概率也将会更大。要想知道第二帧的极线位置,就必须要知道两帧之间的变换矩阵,所以就引出了第一个需要注意的地方,那就是这里的稠密重建方法,必须要 事先给定两帧之间的变换矩阵。多数情况下这个变换矩阵是由前端提供的。

另外,单个像素没有区分性,换句话来说就是鲁棒性较差,但是一个小的区域之内的匹配鲁棒性势必会更好一些,所以书中采用了 块匹配 的方式。

然后就是通过三角化还原出空间点的位置,由于测量会出现误差,所以提出使用深度滤波器进行多次测量,获得一个收敛的结果。高翔在书中提到使用深度滤波器,也就是高斯分布相乘的方式进行滤波。

高斯分布的深度滤波器
为什么就可以直接将两个高斯分布相乘进行滤波呢?书中并未提及原因,实际上我觉得这是一个非常重要的点,至少学会了这一点,对于简单的数据融合,我们没有必要就非要用卡尔曼滤波。

在这里插入图片描述
在《机器人学中的状态估计》2.2.6 高斯概率密度函数的归一化积中有如上这张图,最左和最右的两个正态分布是两次测量,而中间那个就是两次测量融合之后的效果,是不是有那么点像多次测量求平均值的味道,而这个归一化积的过程就是两次测量的分布求积。至于为何多次测量之后会有更大的可能获得一个最好的结果呢?这里我只是贴出了结论,至于更细节和具体的原因,就交由大家自己去学习了!

主要是我尝试解释这个原因,但是发现可能是自己的理解还不够,导致解释之后更乱!

关于深度滤波器,推荐大家看一下这篇博客:《深度滤波器详细解读》

另外的内容大家还是看《十四讲》吧!

============ TODO:补充建图相关内容 ===========

这一讲本来在写的时候,感觉有好多东西写,但是当我开始查看相关论文以及一些博客之后,发现啥也不会写了,书中省略了的一些内容恰恰是一些很难却很有用的内容,所以我建议大家还是直接阅读SVO、DSO或者LSD的论文和代码,不然仅凭书中的介绍,你可能很难理解这其中的技巧和原理。(感觉这一篇写的有点水,没有什么特别干货的东西,待我看些论文,再研究研究,继续补上一些相关内容)

这篇关于解读《视觉SLAM十四讲》,带你一步一步入门视觉SLAM—— 第 13 讲 建图的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1033708

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

MCU7.keil中build产生的hex文件解读

1.hex文件大致解读 闲来无事,查看了MCU6.用keil新建项目的hex文件 用FlexHex打开 给我的第一印象是:经过软件的解释之后,发现这些数据排列地十分整齐 :02000F0080FE71:03000000020003F8:0C000300787FE4F6D8FD75810702000F3D:00000001FF 把解释后的数据当作十六进制来观察 1.每一行数据

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

poj 3181 网络流,建图。

题意: 农夫约翰为他的牛准备了F种食物和D种饮料。 每头牛都有各自喜欢的食物和饮料,而每种食物和饮料都只能分配给一头牛。 问最多能有多少头牛可以同时得到喜欢的食物和饮料。 解析: 由于要同时得到喜欢的食物和饮料,所以网络流建图的时候要把牛拆点了。 如下建图: s -> 食物 -> 牛1 -> 牛2 -> 饮料 -> t 所以分配一下点: s  =  0, 牛1= 1~

poj 2104 and hdu 2665 划分树模板入门题

题意: 给一个数组n(1e5)个数,给一个范围(fr, to, k),求这个范围中第k大的数。 解析: 划分树入门。 bing神的模板。 坑爹的地方是把-l 看成了-1........ 一直re。 代码: poj 2104: #include <iostream>#include <cstdio>#include <cstdlib>#include <al