地图点可以通过关键帧来构造,也可以通过普通帧构造,但是最终,必须是和关键帧对应的,通过普通帧构造的地图点只是临时被Tracking用来追踪用的。

构造函数(地图点3D坐标及其参考帧):

// 参考帧是关键帧,该地图点将于许多帧关键帧对应,建立关键帧之间的共视关系
MapPoint::MapPoint(const cv::Mat &Pos, KeyFrame *pRefKF, Map* pMap)
// 参考帧是普通帧,该地图点只与当前普通帧的特征点对应
MapPoint::MapPoint(const cv::Mat &Pos, Map* pMap, Frame* pFrame, const int &idxF)

地图点和关键帧之间的观测关系是最重要的,参考关键帧是哪一帧,该地图点被哪些关键帧观测到,对应的哪个(idx)特征点?通过两个成员维护:

std::map<KeyFrame*,size_t> mObservations;
// 观测到该地图点的相机数
int nObs;

添加地图点观测:能够观测到同一个地图点的关键帧之间存在共视关系

void MapPoint::AddObservation(KeyFrame* pKF, size_t idx);

删除地图点观测:从当前地图点的mObservation和nObs成员中删掉对应关键帧观测关系,若该关键帧恰好是参考帧,则需要重新指定。当观测相机数小于等于2时,该地图点需要剔除。删掉观测关系,和删掉地图点(以及替换地图点),需要区分开!

void MapPoint::EraseObservation(KeyFrame* pKF);

剔除MapPoint不仅需要删掉地图点中维护的关键帧观测关系,还需要删掉对应关键中对应的地图点,以及Map中该地图点的内存:

void KeyFrame::EraseMapPointMatch(const size_t &idx)
{
unique_lock<mutex> lock(mMutexFeatures);
mvpMapPoints[idx]=static_cast<MapPoint*>(NULL);
} mpMap->EraseMapPoint(this);

下面是一个重要的函数:

void MapPoint::Replace(MapPoint* pMP);

将当前地图点(this),替换成pMp。主要使用在闭环时,调整地图点和关键帧,建立新的关系:

关键帧将联系的this替换成pMap:

pKF->ReplaceMapPointMatch(mit->second, pMP);// KeyFrame中mit->second索引对应的地图点,用pMP替换掉原来的this
pMP->AddObservation(pKF,mit->second);// pMp地图点添加观测关键帧
// 删掉Map中该地图点
mpMap->EraseMapPoint(this);

无论是SetBadFlag()还是Replace(),当前地图点的mbBad标志都被记为true,表明当前地图点是个坏点。

visible和found的区别:该地图点在视野范围内,该地图点有对应特征点的帧数。通常来说,found的地图点一定是visible的,但是visible的地图点很可能not found

float MapPoint::GetFoundRatio()
{
unique_lock<mutex> lock(mMutexFeatures);
return static_cast<float>(mnFound)/mnVisible;
}

GetFoundRatio低表示该地图点在很多关键帧的视野范围内,但是没有匹配上很多特征点。

最后是MapPoint中几个比较重要的函数:

void MapPoint::ComputeDistinctiveDescriptors();
void MapPoint::UpdateNormalAndDepth();
int MapPoint::PredictScale(const float &currentDist, KeyFrame* pKF);

1. 计算地图点描述子:

从mObservations中获取观察到当前地图点的关键帧及对应描述子,描述子放入vDescriptor描述子向量组成的向量中。在这些描述子中,选择距离(类似hamming距离)其他描述子最近的(中值距离最小,看代码去体会一下是什么意思)作为地图点的描述子mDescriptor。

2. 计算地图点平均观测方向和深度

地图点到所有观测到的关键帧相机中心向量,归一化后相加。

深度范围:地图点到参考帧(只有一帧)相机中心距离,乘上参考帧中描述子获取时金字塔放大尺度,得到最大距离mfMaxDistance;最大距离除以整个金字塔最高层的放大尺度得到最小距离mfMinDistance。通常来说,距离较近的地图点,将在金字塔层数较高的地方提取出,距离较远的地图点,在金字塔层数较低的地方提取出(金字塔层数越低,分辨率越高,才能识别出远点)。因此通过地图点的信息(主要是对应描述子),我们可以获得该地图点对应的金字塔层级:

const int level = pRefKF->mvKeysUn[observations[pRefKF]].octave;

从而预测该地图点在什么距离范围内能够被观测到!

3. int MapPoint::PredictScale(const float &currentDist, KeyFrame* pKF)

注意金字塔ScaleFactor和距离的关系:当前特征点对应ScaleFactor为1.2的意思是:图片分辨率下降1.2倍后,可以提取出该特征点(分辨率更高时,肯定也可以提取出,这里取金字塔中能够提取出该特征点最高层级作为该特征点的层级)

同时,由当前特征点的距离,可以推测所在层级。

Map则比较简单,主要负责维护其中关键帧和地图点容器,设置参考地图点用于绘图:

std::set<MapPoint*> mspMapPoints;
std::set<KeyFrame*> mspKeyFrames;

ORB-SLAM(六)MapPoint与Map的更多相关文章

  1. python六剑客:map()、lambda()、filter()、reduce()、推导类表、切片

    一:map():映射 map()有两个参数,一个函数,一个序列,序列中每一个元素都会做为参数传给前边的函数,然后生成新的列表, 第二个参数必须用一个序列:元祖,列表,字符串 >>> ...

  2. MapReduce算法形式六:只有Map独自作战

    案例六:Map独自直接输出 之前一直没有用过这个map独自输出的模式,就算是输出一些简单的我也会经过一次reduce输出,但是,发现这个map输出的结果跟我预想的有点不一样,我一直以为shuffle的 ...

  3. Power BI for Office 365(六)Power Map简介

    如果说Power BI中最给力的功能是什么,我觉得是Power Map.Power Map第一次是出现在SQL Server 2014的新特性里被提及,前身就是GeoFlow.在Power Map下可 ...

  4. 六、es6 map

    一.map的特点 JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键.这给它的使用带来了很大的限制. 为了解决这个问题,ES6 提供了 ...

  5. jQuery 源码解析(六) $.each和$.map的区别

    $.each主要是用来遍历数组或对象的,例如: var arr=[11,12,13,14]; $.each(arr,function(element,index){ //遍历arr数组 console ...

  6. [SLAM] 01. "Simultaneous Localization and Mapping"

    本篇带你认识SLAM,形成客观的认识和体系 一.通过行业招聘初步了解SLAM 发信人: leecty (Terry), 信区: ParttimeJobPost标 题: 创业公司招SLAM 算法工程师发 ...

  7. [SLAM] 01 "Simultaneous Localization and Mapping" basic knowledge

    发信人: leecty (Terry), 信区: ParttimeJobPost标 题: 创业公司招SLAM 算法工程师发信站: 水木社区 (Thu Jun 16 19:18:24 2016), 站内 ...

  8. Map集合、HashMap集合、LinkedHashMap集合、Hashtable集合、Collections工具类和模拟斗地主洗牌和发牌

    1.Map集合概述和特点 * A:Map接口概述  * 查看API可以知道:          * 将键映射到值的对象          * 一个映射不能包含重复的键          * 每个键最多 ...

  9. 常用的SLAM解决方案

    ORB SLAM 可以去Github上自己搜索现成的SLAM程序包 在此基础上做优化 视觉SLAM的分类方法:按摄像头的多少分为单目和双目,按是否使用概率方法分为概率法和图法 链接 学习SLAM重要的 ...

随机推荐

  1. 连接IBM MQ原因码报2035的错误解决办法

    我们的系统使用了ibm mq,用户用来向国家局上报文件和接收文件,前几天用户说上报一直不成功.由于 开发这块程序的人已经辞职了,我觉定在我的机器部署一套,研究一下.我的思路: 在我的机器上安装mq,建 ...

  2. 请求是如何传递给StandardEngine的?

    将请求的传递过程分解学习. CoyoteAdapter将中持有Connector的引用,所以在Coyote这个类中Connector查找它所属的StandardService,而StandardSer ...

  3. HDU 6370 Werewolf 【并查集】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6370 Werewolf Time Limit: 2000/1000 MS (Java/Others)   ...

  4. 几句代码简单实现IoC容器

    前言 最近在调试EasyNetQ代码的时候发现里面有一段代码,就是IoC容器的简单实现,跟着他的代码敲了一遍,发现了奇妙之处.当然也是因为我才疏学浅导致孤陋寡闻了.他的思路就是通过动态调用构造函数生成 ...

  5. table中实现数据上移下移效果

    html 由于vue+Element项目中的table,没有开放的上移下移的api,但是能对数据操作,故思路为数组中的一条数据,再重新添加一条数据,办法有点笨,但是好歹也是实现了,望有好的办法的,请留 ...

  6. Visual Studio2015无法启动IIS Express Web 服务器的解决方案

    有时通过VS2015启动项目会弹出提示框:无法启动IIS Express Web服务器 出现这种提示框有可能是因为此项目的解决方案是从别人电脑中拷贝过来的,所以启动会出现错误. 解决办法就是删除解决方 ...

  7. cmd进入指定的文件夹

    怎么利用cmd进入指定的文件夹呢? 1:win+r ——cmd 2:进入要到达的盘符 (比如我要进入d盘) 3:然后通过  cd d:\project    进入指定的文件夹

  8. 使用Scanner将InputStream类型转换成String

    我们在测试项目中经常会遇到这样的情形: 1. 从文件或网络得到一个InputStream,需要转换成String赋值到别的变量做为另一个方法的入参. 2. 从文件或网络得到一个InputStream后 ...

  9. Oracle模糊查询

    通配符 % 匹配零个或更多的任意字符 _ 匹配一个任意字符 [ ] 匹配指定范围中的一个字符([a-z],[0-9]) [^ ]      不属于指定范围,不包含其中的字符 escape转义 --查询 ...

  10. ObjC之RunTime(下)

    之前通过学习官方文档对runtime有了初步的认识,接下来就要研究学习runtime到底能用在哪些地方,能如何改进我们的程序. 本文也可以从icocoa浏览. Swizzling Swizzling可 ...