orb-slam2学习总结

news2024/12/26 11:47:16

目录

视觉SLAM

1、地图初始化

2、ORB_SLAM地图初始化流程

3、ORB特征提取及匹配

1、对极几何

2、对极约束 (epipolar constraint)

3、基础矩阵F、本质矩阵E

5、单目尺度不确定性

6、单应矩阵(Homography Matrix)

6.1 什么是单应矩阵

6.2 H矩阵求解

7.1 基础要点

7.2  从E矩阵中恢复R、t

7.3  从H矩阵中恢复R、t

7.4 R、t值验证

7、三角化             

7.1什么是三角化

7.2 三角化求解

8、关键步骤总结

9、参考资料


视觉SLAM

一、知识点

1、地图初始化

视觉slam中,地图初始化是一个非常重要的步骤,它决定了后续的跟踪、建图等模块的效果。简单来说,初始化的目的是利用前几帧图像,计算出相机位姿,并且构建出第一批3D地图点第一批3D地图点为跟踪、建图等模块提供了一个初始的地图,这样后续的模块就可以利用这些地图点进行跟踪、建图等工作。

双目由于已知两个相机的内外参,可以直接三角化出3D点。三角化是单目的一个步骤,所以双目初始化比较简单。

RGBD可以直接通过深度值还原3D坐标,更加简单。 

配置了IMU之后实际也可以直接获得两个相机之间的姿态,也可以直接三角化出3D点(虽然IMU初始化需要考虑IMU参数的初始化,但是这部分内容不在本文的讨论范围内)。

2、ORB_SLAM地图初始化流程

3、ORB特征提取及匹配

特征点提取是一个比较独立的内容,对于ORB特征提取可以参考这篇文章:https://zeal-up.github.io/2023/05/18/orbslam/orbslam3-ORBextractor/

备注:根据描述子之间的距离来寻找两帧间 距离最近的关键件,达到关键点匹配的效果。

  1. 对极几何及对极约束

1、对极几何

通常,我们会将第一帧图像当作参考帧,也就是世界坐标系。第二帧相机的位姿也就是相对于第一帧相机的位姿。

总结:

利用两相机在空间中成像的(空间几何关系,也叫立体几何)规律,进而求解此时相机的位姿态。因此就需要用到特征提取步骤提取到得匹配点,利用匹配点利用对极约束求解相机位姿。

那么什么是对极约束呢?

2、对极约束 (epipolar constraint)

3、基础矩阵F、本质矩阵E

   Foundamental Matrix、Essential Matrix

  1. 对极约束的几何意义

备注

当需要寻找关键点在另外一张图片上投影点时候,评估相机姿态质量的时候,同样道理。

又或者在极线方向上寻找匹配点,避免全图片检索,提到检索效率。这些都是对极约束的应用。

  1. 本质矩阵和基础矩阵求解
  • 方程求解

  • opencv求解

5、单目尺度不确定性

在看对极几何的图

总结:

尺度信息在等式中无法接着求解,只能利用别的设备增加深度信息才能更好求解尺度。

6、单应矩阵(Homography Matrix)

6.1 什么是单应矩阵

前面讨论基础矩阵的概念以及如何从一些匹配点对关系中求解基础矩阵。我们没有对关键点是否在一个平面上进行任何假设。但是,如果我们假设关键点在一个平面上,那么我们就可以使用单应矩阵(Homography Matrix)来求解相机之间的位姿。当匹配点对的关键点都是在3D空间中一个平面上时,这些点对关系可以通过单应矩阵来描述(相差一个常量系数)

备注:要求匹配点对应点对是3D空间,同一平面上的。

如下图:

6.2 单应矩阵的应用

  • 相机位姿态求解
  • 图像拼接

链接:

超详细!从单应矩阵推导到自动驾驶环视投影应用 | Zeal's Blog

6.2 H矩阵求解

  • 求解推导

  • OpenCV接口

  1. 位姿求解

如何从H、E矩阵恢复R、t?

7.1 基础要点

7.2  从E矩阵中恢复R、t

可使用opencv接口

7.3  从H矩阵中恢复R、t

从H矩阵恢复R、t有多种方法,论文中的方法叫Faugeras SVD-based decomposition,最终可以求解出8种解。另外一种有名的数值解法(通过奇异值分解)叫

SVD-based decomposition

OpenCV的接口使用的是分析解法:https://inria.hal.science/inria-00174036v3/documentOpenCV的接口最终返回4种解

OpenCV的接口使用说明:cv::decomposeHomographyMat

7.4 R、t值验证

从E、H分解出来的矩阵后,需要选择出正确的R、t

无论从E矩阵还是H矩阵中恢复出R、t,都会得到多种解。

我们需要从这些解中选择出正确的解。 最简单的做法是利用分解出的R、t对匹配点进行三角化,并检查该3D点在两个相机下的深度值,3D点必须在两个相机下都是正的才是正确的解。

对于单应矩阵的分解结果,OpenCV提供了一个函数可以帮助我们选择正确的解:cv::filterHomographyDecompByVisibleRefpoints

在ORB_SLAM中,对于每一种解,都会对所有匹配点进行三角化,对三角化出来的点,会进行很多步骤的检查,最后选择拥有最多内点的解作为正确的解

备注:什么是内点

7、三角化             

7.1什么是三角化

当求解出位姿态后,需要利用位姿,联合匹配点关系,求解出三维点坐标。

7.2 三角化求解

用SVD求解上述方程,求解出的3D坐标有4个元素,需要将第四个元素归一化为1。这里把ORB_SLAM的这部分代码也贴出来

/** 
 * @brief 三角化获得三维点
 * @param x_c1 点在关键帧1下的归一化坐标
 * @param x_c2 点在关键帧2下的归一化坐标
 * @param Tc1w 关键帧1投影矩阵  [K*R | K*t]
 * @param Tc2w 关键帧2投影矩阵  [K*R | K*t]
 * @param x3D 三维点坐标,作为结果输出
 */
bool GeometricTools::Triangulate(
    Eigen::Vector3f &x_c1, Eigen::Vector3f &x_c2, Eigen::Matrix<float,3,4> &Tc1w, Eigen::Matrix<float,3,4> &Tc2w,
    Eigen::Vector3f &x3D)
{
    Eigen::Matrix4f A;
    // x = a*P*X, 左右两面乘x的反对称矩阵 a*[x]^ * P * X = 0 ,[x]^*P构成了A矩阵,中间涉及一个尺度a,因为都是归一化平面,但右面是0所以直接可以约掉不影响最后的尺度
    //  0 -1 v    P(0)     -P.row(1) + v*P.row(2)
    //  1 0 -u *  P(1)  =   P.row(0) - u*P.row(2) 
    // -v u  0    P(2)    u*P.row(1) - v*P.row(0)
    // 发现上述矩阵线性相关(第一行乘以-u加上第二行乘以-v等于第三行),所以取前两维,两个点构成了4行的矩阵(X分别投影到相机1和相机2),就是如下的操作,求出的是4维的结果[X,Y,Z,A],所以需要除以最后一维使之为1,就成了[X,Y,Z,1]这种齐次形式
    A.block<1,4>(0,0) = x_c1(0) * Tc1w.block<1,4>(2,0) - Tc1w.block<1,4>(0,0);
    A.block<1,4>(1,0) = x_c1(1) * Tc1w.block<1,4>(2,0) - Tc1w.block<1,4>(1,0);
    A.block<1,4>(2,0) = x_c2(0) * Tc2w.block<1,4>(2,0) - Tc2w.block<1,4>(0,0);
    A.block<1,4>(3,0) = x_c2(1) * Tc2w.block<1,4>(2,0) - Tc2w.block<1,4>(1,0);

    // 解方程 AX=0
    Eigen::JacobiSVD<Eigen::Matrix4f> svd(A, Eigen::ComputeFullV);

    Eigen::Vector4f x3Dh = svd.matrixV().col(3);

    if(x3Dh(3)==0)
        return false;

    // Euclidean coordinates
    x3D = x3Dh.head(3)/x3Dh(3);

    return true;
}

也可以使用opencv接口进行三角化,且可以批量操作:cv::triangulatePoints

8、关键步骤总结

  • 特征点提取和匹配,得到如下效

  • 如何从匹配的特征点中,恢复相机之间的相对位姿

利用E、F矩阵怎么求解位姿态

利用H矩阵怎么求解位姿

利用H矩阵进行图像拼

  • 矩阵中分解R、t
  • 利用R、t进行三角化

9、参考资料

orbslam

ORB-SLAM3保姆级解析:地图初始化(基础矩阵/单应矩阵/三角化的实际应用)

激光slam

详解激光雷达点云处理那些事,点云预处理、感知、定位 - 哔哩哔哩 (bilibili.com)

立体几何

立体视觉入门指南(6):对级约束与Fusiello法极线校正 - 知乎 (zhihu.com)

视觉SLAM中的对极约束、三角测量、PnP、ICP问题

视觉SLAM中的对极约束、三角测量、PnP、ICP问题 - 古月居 (guyuehome.com)

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

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

相关文章

没有明确的报错信息,阿里云国际版Windows服务器无法远程连接

在远程连接失败时&#xff0c;如果您没有收到系统返回的报错信息&#xff0c;并且ECS实例是运行中的状态&#xff0c;然后再根据以下步骤进行排查&#xff1a; 步骤一&#xff1a;使用阿里云Workbench工具测试远程登录 步骤二&#xff1a;检查是否有收到黑洞通知 步骤三&…

Zygote 进程启动过程

首语 在Android系统中&#xff0c;DVM(Dalvik虚拟机)和ART、应用程序进程以及运行系统的关键服务的SystemServer进程都是由Zygote进程创建的&#xff0c;也可以将其称之为孵化器&#xff0c;它通过fork(复制进程)的形式来创建应用程序进程和SystemServer进程。 Zygote进程是在…

AnythingLLM:基于RAG方案构专属私有知识库(开源|高效|可定制)

一、前言 继OpenAI和Google的产品发布会之后&#xff0c;大模型的能力进化速度之快令人惊叹&#xff0c;然而&#xff0c;对于很多个人和企业而言&#xff0c;为了数据安全不得不考虑私有化部署方案&#xff0c;从GPT-4发布以来&#xff0c;国内外的大模型就拉开了很明显的差距…

Oracle(2-17) RMAN Maintenance

文章目录 一、基础知识1、Retention Policy 保留政策2、Recovery Window - Part 1 恢复窗口-第1部分3、Cross Checking 交叉检查4、The CROSSCHECK Command CROSSCHECK命令5、OBSOLETE VS EXPIRED 过时与过期6、Deleting Backups and Copies 删除备份和副本7、The DELETE Comma…

极狐GitLab CI/CD 变量黑魔法之自定义变量

极狐GitLab CI/CD 变量是指一系列的环境变量&#xff0c;用来帮助我们控制 CI/CD Job 或 Pipeline 的行为&#xff0c;存储一些可以复用的信息&#xff0c;避免在 .gitlab-ci.yml 中形成硬编码。 极狐GitLab CI/CD 变量分为预定义变量(predefined CI/CD variables) 和 自定义变…

图论-并查集

并查集(Union-find Sets)是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并问题.一些常见的用途有求连通子图,求最小生成树Kruskal算法和最近公共祖先(LCA)等. 并查集的基本操作主要有: .1.初始化 2.查询find 3.合并union 一般我们都会采用路径压缩 这样…

flex布局,换行的元素上下设置间距

要生成的效果图如下&#xff1a; display:flexflex-direction: row;flex-wrap: wrap;当我们使用弹性盒子布局后&#xff0c;默认元素是没有外边距的&#xff0c;紧挨着样式就有点丑&#xff0c;如果想使换行后&#xff0c;元素的外边距有个距离&#xff0c;可以用如下方法解决…

Apache Flink(十二):Flink集群部署-Flink On Yarn

🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录

Python学习笔记(四):函数的定义、函数的返回值、None类型、函数说明文档、函数的嵌套调用、局部变量、全局变量、global关键字

目录 一、函数介绍 1. 函数是&#xff1a; 2. 使用函数的好处是&#xff1a; 二、函数的定义&#xff1a; 三、函数的参数 1.传入参数的功能是&#xff1a; 2.函数的传入参数 - 传参定义 3.注意事项&#xff1a; 4.练习&#xff1a;测量体温 四、函数的返回值 1.函数…

Axure元件基本介绍进阶

Axure元件基本介绍进阶 1.Axure元件基本介绍1.在 Axure 中&#xff0c;元件是构建原型的基本构成单元&#xff0c;能够帮助设计师快速创建、重复使用和管理设计元素。以下是 Axure 中元件的基本介绍&#xff1a;1.基本元件&#xff1a; 2.基本元件的使用一.【举例说明】积木&am…

基于 Game Object Conversion 和 SubScene 的 DOTS 开发工作流(干货满满!)

(译前言: Unity DOTS提出了一套全新的开发技术栈, 但目前少有精讲如何结合现有工作流进行开发的资料, 外网 这篇文章 (Game Object Conversion and SubScene) 详细解构了基于 GameObject 和 Subscene 的工作流程和原理, 要求读者对 DOTS/ECS 有基本的了解, 虽然非常之长, 但值得…

8 Buildroot 根文件系统构建

一、根文件系统简介 根文件系统一般也叫做 rootfs&#xff0c;这个是属于 Linux 内核的一部分。 根文件系统首先是一种文件系统&#xff0c;该文件系统不仅具有普通文件系统的存储数据文件的功能&#xff0c;但是相对于普通的文件系统&#xff0c;它的特殊之处在于&#xff0c;…

flutter的ListView和SingleChildScrollView有什么区别?他们的使用场景有什么不一样?

文章目录 简介ListViewSingleChildScrollView使用场景的不同 简介 ListView和SingleChildScrollView都是在Flutter中用于处理滚动内容的组件&#xff0c;但它们有一些关键的区别。 ListView 多个子元素&#xff1a; ListView是一个滚动的可滚动组件&#xff0c;通常用于包含多…

看图识药,python开发实现基于VisionTransformer的119种中草药图像识别系统

中药药材图像识别相关的实践在前面的系列博文中已经有了相应的实践了&#xff0c;感兴趣的话可以自行移步阅读即可&#xff0c;每篇文章的侧重点不同&#xff1a; 《python基于轻量级GhostNet模型开发构建23种常见中草药图像识别系统》 《基于轻量级MnasNet模型开发构建40种常…

HTML中常用表单元素使用(详解!)

Hi i,m JinXiang ⭐ 前言 ⭐ 本篇文章主要介绍HTML中常用表单元素使用以及部分理论知识 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f349;博主收将持续更新学习记录获&#xff0c;友友们有任何问题可以在评论区留言 …

云基础软件深化合作,云轴科技ZStack与麒麟软件战略签约

12月8日&#xff0c;云轴科技ZStack与麒麟软件战略合作签约仪式在北京举行&#xff0c;双方对过往紧密合作表达了充分肯定&#xff0c;并就进一步联合技术创新、打造重点行业标杆和持续赋能客户达成高度共识。云轴科技创始人&CEO张鑫和麒麟软件高级副总经理谢文征共同见证双…

112. 路径总和(Java)

目录 解法&#xff1a; 官方解法&#xff1a; 方法一&#xff1a;广度优先搜索 思路及算法 复杂度分析 时间复杂度&#xff1a; 空间复杂度&#xff1a; 方法二&#xff1a;递归 思路及算法 复杂度分析 时间复杂度&#xff1a; 空间复杂度&#xff1a; 给你二叉树的…

【毕业设计】基于STM32的解魔方机器人

1、方案设计 1.采用舵机作为魔方机器人的驱动电机&#xff0c;从舵机的驱动原理可知&#xff1a;舵机运行的速度和控制器的主频没有关系&#xff0c;所以采用单片机和采用更高主频的嵌入式处理器相比在控制效果上没有什么差别。单片机编程过程简单&#xff0c;非常容易上手&am…

c#_sqlserver_三层架构winform学生信息管理及选课系统

基本功能包括管理员登录、注册学生账号、删除学生信息、查找学生信息、发布课程、修改课程、删除课程等。 教师端 登录&#xff1a;管理员登陆&#xff0c;拥有相应账号即可登录&#xff08;后台注册&#xff09;。注册学生账号&#xff1a;管理员可给学生分配学号&#xff0…

Linux Mint编译安装Qemu

文章目录 前言1. 准备Qemu源码包2. 编译安装2.1 首次尝试编译2.2 安装python3-venv2.3 安装sphinx2.4 安装sphinx-rtd-theme2.4 安装ninja2.6 安装编译器 3. 重新编译并安装4. 进行固件仿真4.1 准备固件4.2 Binwalk解析文件4.3 看一下文件结构4.4 安装sasquatch4.5 重新解析文件…