ORB-SLAM (四)tracking单目初始化
单目初始化以及通过三角化恢复出地图点
单目的初始化有专门的初始化器,只有连续的两帧特征点均>100个才能够成功构建初始化器。
// mvbPreMatched是第一帧中的所有特征点;mvIniMatches标记匹配状态,未匹配上的标为-1;如果返回nmatches<100,初始化失败,重新初始化过程
int nmatches = matcher.SearchForInitialization(mInitialFrame,mCurrentFrame,mvbPrevMatched,mvIniMatches,);
若成功获取满足特征点匹配条件的连续两帧,并行计算分解基础矩阵和单应矩阵(获取的点恰好位于同一个平面),得到帧间运动(位姿),vbTriangulated标记一组特征点能否进行三角化。mvIniP3D是cv::Point3f类型的一个容器,是个存放3D点的临时变量。
该函数对应Initialize.cpp文件,需要完成较多工作,后面再介绍。
mpInitializer->Initialize(mCurrentFrame, mvIniMatches, Rcw, tcw, mvIniP3D, vbTriangulated)
最后初始化两帧位姿并且将mvIniP3D中的点包装成MapPoint,构建初始地图。
mInitialFrame.SetPose(cv::Mat::eye(,,CV_32F));
mCurrentFrame.SetPose(Tcw);
CreateInitialMapMonocular();
构建初始地图就是将这两关键帧以及对应的地图点加入地图(mpMap)中,需要分别构造关键帧以及地图点
KeyFrame* pKFini = new KeyFrame(mInitialFrame,mpMap,mpKeyFrameDB);
KeyFrame* pKFcur = new KeyFrame(mCurrentFrame,mpMap,mpKeyFrameDB);
地图点中需要加入其一些属性:
1. 观测到该地图点的关键帧(对应的关键点);
2. 该MapPoint的描述子;
3. 该MapPoint的平均观测方向和观测距离。
for(size_t i=; i<mvIniMatches.size();i++)
{
if(mvIniMatches[i]<)
continue;
//Create MapPoint from mvIniP3D
cv::Mat worldPos(mvIniP3D[i]);
MapPoint* pMP = new MapPoint(worldPos,pKFcur,mpMap);
pKFini->AddMapPoint(pMP,i);
pKFcur->AddMapPoint(pMP,mvIniMatches[i]);
pMP->AddObservation(pKFini,i);
pMP->AddObservation(pKFcur,mvIniMatches[i]);
pMP->ComputeDistinctiveDescriptors();
pMP->UpdateNormalAndDepth();
mCurrentFrame.mvpMapPoints[mvIniMatches[i]] = pMP;
mCurrentFrame.mvbOutlier[mvIniMatches[i]] = false;
mpMap->AddMapPoint(pMP);
}
还需要更新关键帧之间连接关系(以共视地图点的数量作为权重):
pKFini->UpdateConnections();
pKFcur->UpdateConnections();
对这两帧姿态进行全局优化重投影误差(LM):
Optimizer::GlobalBundleAdjustemnt(mpMap,);
注意这里使用的是全局优化,和回环检测调整后的大回环优化使用的是同一个函数。
接下来,需要归一化第一帧中地图点深度的中位数;如果深度<0或者这时发现优化后第二帧追踪到的地图点<100,也需要重新初始化。
否则,将深度中值作为单位一,归一化第二帧的位姿与所有的地图点。
float medianDepth = pKFini->ComputeSceneMedianDepth();
float invMedianDepth = 1.0f/medianDepth; if(medianDepth< || pKFcur->TrackedMapPoints()<)
{
cout << "Wrong initialization, reseting..." << endl;
Reset();
return;
} // Scale current pose
cv::Mat Tc2w = pKFcur->GetPose();
Tc2w.col().rowRange(,) = Tc2w.col().rowRange(,)*invMedianDepth;
pKFcur->SetPose(Tc2w); // Scale points
vector<MapPoint*> vpAllMapPoints = pKFini->GetMapPointMatches();
for(size_t iMP=; iMP<vpAllMapPoints.size(); iMP++)
{
if(vpAllMapPoints[iMP])
{
MapPoint* pMP = vpAllMapPoints[iMP];
pMP->SetWorldPos(pMP->GetWorldPos()*invMedianDepth);
}
}
最后和StereoInitialization()中一样,需要更新局部地图,局部关键帧和局部地图点;并且更新LastFrame,LastKeyFrame,以及当前帧的ReferenceKF(上一帧,上一关键帧,参考关键帧)。
这就是单目初始化的大体步骤,其中最关键算法是通过初始连续两帧的对极约束恢复出相机姿态和地图点的部分(Initializer.cpp)留在下一节说。
ORB-SLAM (四)tracking单目初始化的更多相关文章
- ORB-SLAM3 细读单目初始化过程(上)
作者:乔不思 来源:微信公众号|3D视觉工坊(系投稿) 3D视觉精品文章汇总:https://github.com/qxiaofan/awesome-3D-Vision-Papers/ 点击上方&qu ...
- ORBSLAM2单目初始化过程
ORBSLAM2单目初始化过程 转自博客:https://blog.csdn.net/zhubaohua_bupt/article/details/78560966 ORB单目模式的初始化过程可以分为 ...
- ORB-SLAM2 论文&代码学习 —— 单目初始化
转载请注明出处,谢谢 原创作者:Mingrui 原创链接:https://www.cnblogs.com/MingruiYu/p/12358458.html 本文要点: ORB-SLAM2 单目初始化 ...
- ORB-SLAM (四)Initializer单目初始化
一. 通过对极约束并行计算F和H矩阵初始化 VO初始化目的是为了获得准确的帧间相对位姿,并通过三角化恢复出初始地图点.初始化方法要求适用于不同的场景(特别是平面场景),并且不要进行人为的干涉,例如选取 ...
- 单目、双目和RGB-D视觉SLAM初始化比较
无论单目.双目还是RGB-D,首先是将从摄像头或者数据集中读入的图像封装成Frame类型对象: 首先都需要将彩色图像处理成灰度图像,继而将图片封装成帧. (1) 单目 mCurrentFrame = ...
- Semantic Monocular SLAM for Highly Dynamic Environments面向高动态环境的语义单目SLAM
一.摘要 当前单目SLAM系统能够实时稳定地在静态环境中运行,但是由于缺乏明显的动态异常处理能力,在动态场景变化与运动中往往会失败.作者为解决高度动态环境中的问题,提出一种语义单目SLAM架构,结合基 ...
- 从零开始一起学习SLAM | 神奇的单应矩阵
小白最近在看文献时总是碰到一个奇怪的词叫“homography matrix”,查看了翻译,一般都称作“单应矩阵”,更迷糊了.正所谓:“每个字都认识,连在一块却不认识”就是小白的内心独白.查了一下书上 ...
- 三角化---深度滤波器---单目稠密重建(高翔slam---十三讲)
一.三角化 [1]三角化得到空间点的三维信息(深度值) (1)三角化的提出 三角化最早由高斯提出,并应用于测量学中.简单来讲就是:在不同的位置观测同一个三维点P(x, y, z),已知在不同位置处观察 ...
- Ubuntu16.04下编译安装及运行单目ORBSLAM2
官网有源代码和配置教程,地址是 https://github.com/raulmur/ORB_SLAM2 1 安装必要工具 首先,有两个工具是需要提前安装的.即cmake和Git. sudo apt- ...
随机推荐
- 让ADO.NET Entity Framework 支持ACCESS数据库
如写的不好请见谅,本人水平有限. 个人简历及水平:. http://www.cnblogs.com/hackdragon/p/3662599.html 接到一个程序和网页交互的项目,用ADO.NET ...
- 每日linux命令之kill
1.命令格式: kill[参数][进程号] 2.命令功能: 发送指定的信号到相应进程.不指定型号将发送SIGTERM(15)终止指定进程.如果任无法终止该程序可用“-KILL” 参数,其发送的信号为S ...
- Android(java)学习笔记20:UDP协议发送数据
1. UDP协议发送数据:我们总是先运行接收端,再运行发送端发送端: package cn.itcast_02; import java.io.IOException; import java.net ...
- HDU 3613 扩展KMP
暴力枚举大水题,判断回文,扩展KMP #include <cstdio> #include <cstring> #include <algorithm> using ...
- luogu4566 [Vani有约会]雨天的尾巴
题目 线段树合并的板子题目了,写一写对线段树合并的理解 首先线段树合并就是把一大堆权值线段树合并起来的算法 尽管复杂度看起来并不是非常科学,但是确是非常优秀的\(O(nlogn)\) 主要的写法两种 ...
- POJ 1416 Shredding Company【dfs入门】
题目传送门:http://poj.org/problem?id=1416 Shredding Company Time Limit: 1000MS Memory Limit: 10000K Tot ...
- VMWARE下CentOS7虚拟机网络配置
注:本文仅针对新装的虚拟机,#ip addr 获取不到ip信息,无法连接网络的情况提供一种参考解决方案. 1.左上角点击“编辑”->“虚拟网络编辑器”.新建一个NAT模式的网络. 2.配置虚拟机 ...
- NW.js开发环境的搭建
写在前面: 之前一直在找关于在mac怎么搭建nw.js的开发环境,苦于自己也没有很深入的理解,其实看看官方文档就差不多知道mac下要怎么整了. 官方文档的图: 正题开始: 先去下载一个nw.js的安装 ...
- 【luogu P3368 树状数组2】 模板
题目链接:https://www.luogu.org/problemnew/show/P3368 #include<iostream> #include<cstdio> #in ...
- 全局变量&局部变量&Static存储&Register变量
1.局部变量 局部变量也称为内部变量.局部变量是在函数内作定义说明的.其作用域仅限于函数内:函数的形参就是局部变量: 2.全局变量 全局变量也称为外部变量,它是在函数外部定义的变量.全局变量的说明符为 ...