讲解关于slam一系列文章汇总链接:史上最全slam从零开始,针对于本栏目讲解的(01)ORB-SLAM2源码无死角解析链接如下(本文内容来自计算机视觉life ORB-SLAM2 课程课件): (01)ORB-SLAM2源码无死角解析-(00)目录_最新无死角讲解:https://blog.csdn.net/weixin_43013761/article/details/123092196 文末正下方中心提供了本人 联系方式, 点击本人照片即可显示 W X → 官方认证 {\color{blue}{文末正下方中心}提供了本人 \color{red} 联系方式,\color{blue}点击本人照片即可显示WX→官方认证} 文末正下方中心提供了本人联系方式,点击本人照片即可显示WX→官方认证
一、前言在前面的文章中,已经对单目初始化进行了相对比较详细的介绍,比如针对于 src/Tracking.cc 文件中 MonocularInitialization() 函数讲解。但是之前主要讲解内容是如何求解相机的姿,以及特征点的三角化。直接略过了特征匹配的内容。那么现在来看看其中其中的具体内容,做一个细致的分析。
在 MonocularInitialization() 函数中,可以看到如下代码,其就是我们进行要进行讲解的主角:
// Step 3 在mInitialFrame与mCurrentFrame中找匹配的特征点对
ORBmatcher matcher(
0.9, //最佳的和次佳特征点评分的比值阈值,这里是比较宽松的,跟踪时一般是0.7
true); //检查特征点的方向
// 对 mInitialFrame,mCurrentFrame 进行特征点匹配
// mvbPrevMatched为参考帧的特征点坐标,初始化存储的是mInitialFrame中特征点坐标,匹配后存储的是匹配好的当前帧的特征点坐标
// mvIniMatches 保存参考帧F1中特征点是否匹配上,index保存是F1对应特征点索引,值保存的是匹配好的F2特征点索引
int nmatches = matcher.SearchForInitialization(
mInitialFrame,mCurrentFrame, //初始化时的参考帧和当前帧
mvbPrevMatched, //在初始化参考帧中提取得到的特征点
mvIniMatches, //保存匹配关系
100); //搜索窗口大小
其中创建 ORBmatcher 类对象的代码是十分简单的,设置最佳的和次佳特征点评分的比值阈值,值越大则匹配条件越宽松,以及是否检测特征点的方向。 另外就是调用了 SearchForInitialization,从名字也可以看出,其是为了初始化过程中的特征匹配。主要作用为: 单目初始化中用于参考帧和当前帧的特征点匹配。下面对其进行详细讲解。
二、逻辑分析首先要明白该函数的目的是什么,返回的结果是什么,这是核心要点。首先先其传入两帧图像mInitialFrame(参考帧或者初始帧),mCurrentFrame(当前帧),都为 Frame 类对象。另外还传入了参数 mvbPrevMatched,其为初始化参考帧中提取到特征点的坐标,但是后续会发生改变,匹配完成之后,该变量变更为保存匹配好的当前帧特征点坐标;mvIniMatches 初始记录为参考帧特征点与当前帧特征点的匹配关系,初始默认值都为-1(表示没有匹配到特征点)。mvIniMatches的所索引表示参考帧中第几个特征点,索引对应的值表示当前帧与值匹配特征点的序列。比如,mvIniMatches[1]=3,其含义为,参考帧第1个特征点与当前帧第三个特征点匹配。
传入的四个变量 mInitialFrame,mCurrentFrame,mvbPrevMatched,mvIniMatches 在 SearchForInitialization 函数中等价的局部变量为 F1,F2,vbPrevMatched,vnMatches12。另外还有一个参数 windowSize 表示搜索窗口大小。也就是 vnMatches12 与 mvIniMatches 等价,vnMatches12 [1]=3 其含义也为,参考帧第1个特征点与当前帧第三个特征点匹配。那么反过来 vnMatches21[1]=3则表示当前帧第1个特征点与参考帧第三个特征点匹配。
(1)构建旋转直方图 旋转直方图,首先计算一对匹配的ORB特征点角度差值,然后根据角度差进行归类: 如把360°划分成多个bin(扇形区域),源码中每个扇形区域的角度为HISTO_LENGTH=30,共分成360/30=12个bin。后续会根据一对特征点的角度差,分配到所属的bin之中。
(2)搜索半径内候选特征点 实现该函数功能的代码为 F2.GetFeaturesInArea。这里的F2表示为当前帧。该函数需要传入参考帧(F1)特征点的像素坐标,其会以该像素坐标为中心,windowSize=100为半径,找到参考帧该圆内的所有特征点,然后返回特征点的索引。当前帧与这些索引点对应的特征点,也称为参考帧中特征点对应于当前帧的候选特征点。那么这里可能存在疑问,为什么在windowSize=100范围内搜索,就行了,而不需搜索整张图像特征点。来查看下图: 因为在单目初始化的时候,是连续的两帧进行特征匹配,也就是说,同一个特征点在帧图像中的偏移是不会太大的。
(3)遍历寻找最优与次优 根据(2), 已经搜索到了参考帧特征点对应于当前帧候选特征点。那么下面就是进行特征匹配了,即参考帧特征点与其在当前帧所有候选特征点进行特征匹配。两个特征点是否能够匹配,主要是计算其描述子的汉明距离。候选特征点中汉明距离最小的特征点为最优特征点,记录在 bestDist 局部变量中。汉明距离第二小的特征点为次优特征点。但是这里大家要注意两个点:首先找到最优特征点之后,并且该最优特征点的汉明距离低于 TH_LOW,才有可能被认为匹配成功;除此之外,还需要最优与次优特征点辨识度比较高,即他们与参考帧特征点的汉明距离差值不能太小,也就是最优与次优特征点不能太接近,对应的判断核心代码为 bestDist=FRAME_GRID_COLS) return vIndices; // 计算圆所在的右边界网格列索引 const int nMaxCellX = min((int)FRAME_GRID_COLS-1, (int)ceil((x-mnMinX+r)*mfGridElementWidthInv)); // 如果计算出的圆右边界所在的网格不合法,说明该特征点不好,直接返回空vector if(nMaxCellX=FRAME_GRID_ROWS) return vIndices; const int nMaxCellY = min((int)FRAME_GRID_ROWS-1,(int)ceil((y-mnMinY+r)*mfGridElementHeightInv)); if(nMaxCellY0) 后面条件 (maxLevel>=0)肯定成立 //? 改为 const bool bCheckLevels = (minLevel>=0) || (maxLevel>=0); const bool bCheckLevels = (minLevel>0) || (maxLevel>=0); // Step 2 遍历圆形区域内的所有网格,寻找满足条件的候选特征点,并将其index放到输出里 for(int ix = nMinCellX; ix
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?