当前位置:主页 > 技术文档 > ORB-SLAM2 下载

ORB-SLAM2源码详解 中文超清版

  • 更新:2020-11-28 08:54:56
  • 大小:2.50 MB
  • 热度:666
  • 审核:戴正青
  • 类别:技术文章
  • 格式:PDF

  • 资源介绍
  • 相关推荐

在这篇文章里我们主要开始对跟踪线程进行介绍:

在orb_slam整体编程思路及代码解析(1)中我们发现,Tracking线程的入口是TrackMonocular,其中GrabImageMonocular返回位姿。

FUNCTION1:Tracking的构造函数

默认把跟踪状态设为NO_IMAGES_YET,定位跟踪模式,默认的其他参数,诸如字典,图像画布,地图画布,地图,关键帧数据库等都是system.cc类里定义的对象。也从配置文件中传入了相机的内参,图像校正系数,帧率,图像金字塔和角点提取的基本参数,这些参数都是这个类的元素等。
tracking过程都会用到mpORBextractorLeft作为特征点提取器, 在单目初始化的时候,会用mpIniORBextractor来作为特征点提取器,两者的区别是后者比前者最多提出的点数多一倍。     

FUNCTION1.1:ORBextractor的构造函数

是构造函数,传入features_num最多提取的特征点的数量,scale_factor金字塔图像之间的尺度参数,levels_num金字塔的层数,default_fast_threshold默认fast  角点检测的时候的阈值,为了防止用默认阈值fast角点检测检测的特征数过少,添加设置min_fast_threshold最小的fast特征检测阈值,以保证检测的特征数目。每一层都有一些属性参数,比如mvScaleFactor、mvLevelSigma2、mvInvScaleFactor、mvInvLevelSigma2等,以及给每层分配待提取的特征数,具体通过等比数列求和的方式,求出每一层应该提取的特征数,把每一层的特征点数都放在mnFeaturesPerLevel中,值得注意的是第零层的特征点数是nfeatures×(1-1/scaleFactor)/(1-(1/scaleFactor)^nlevels),然后下一层是上一层点数的1/scaleFactor倍。以此类推,最后一层兜底。然后复制训练的模板,在计算描述子的时候会用到。最后通过求x坐标对应在半径为HALF_PATCH_SIZE的圆上的y坐标,标出了一个圆形区域用来求特征点方向。相关内容可以参考Oriented FAST and Rotated BRIEF。

FUNCTION2:GrabImageMonocular

这个函数先把图片转换成了灰度图像,然后跟据跟踪的状态构造关键帧,再是进行跟踪得到当前帧的位姿。

FUNCTION2.1:Frame的构造函数

传入图像,时间戳,特征点提取器,字典,内参矩阵等参数来构造关键帧,首先把要构造金字塔的相关参数给Frame类中的跟金字塔相关的元素。然后提取ORB特征, 这一步调用了重载了函数调用操作符operator()。

FUNCTION2.1.1:operator()

传入的图像必须是灰度图像,然后构造图像金字塔。相关内容可以参考:

ORB_SLAM2 源码阅读 ORB_SLAM2::ORBextractor。

FUNCTION2.1.1.1:ComputePyramid(image)

这个函数通过传入的图像来构造nlevel层金字塔,level层是level-1层用resize函数得到大小为level-1层大小的scale倍的线性插值后的图像,为了方便做一些卷积计算,所以用copyMakeBorder函数来做边界填充。填充类型是BORDER_REFLECT_101(反射101),例如:gfedcb|abcdefgh|gfedcba。

FUNCTION2.1.1.2:ComputeKeyPointsOctTree(allKeypoints)

这个函数为了计算金字塔每一层的兴趣点,找到FAST关键点,在操作上是依次针对图像金字塔的每一层图像进行的,首先在图像四周去掉长度为EDGE_THRESHOLD-3个单位的像素点的边界,对去掉边界后的图像网格化,每个窗口的大小为w个像素点的大小,然后依次在划分好的窗口中提取FAST关键点,这样做的目的是为了使得每个网格都有特征,从而使得特征点在图像上的分布相对均匀点。如果存在有的窗口中提取的特征点数为0,则降低阈值继续提取,然后对提取出了的关键点换算出其位于(level层的被裁掉边界图像)的位置,并每个窗口中的关键点存入vToDistributeKeys容器中,vToDistributeKeys容器就暂时保存着level层图像的关键点。然后将这些特征点送入DistributeOctTree函数,剔除一些关键点。将剔除后留下的关键点存入allKeypoints[level]容器中。
FUNCTION2.1.1.2.1:DistributeOctTree(vToDistributeKeys, minBorderX, maxBorderX, minBorderY, maxBorderY,mnFeaturesPerLevel[level], level);
先用(maxX-minX)/(maxY-minY)来确定四叉数有几个初始节点,这里有 bug,如果输入的是一张 宽高比 小于 0.5 的图像,nIni 计算得到 0,下一步计算 hX 会报错,例如round(640/480)=1,所以只有一个初始节点,(UL,UR,BL,BR)就会分布到被裁掉边界后的图像的四个角。把所有的关键点分配给属于它的节点,当节点所分配到的关键点的个数为1时就不再进行分裂,当节点没有分配到关键点时就删除此节点。再根据兴趣点分布,利用四叉树方法对图像进行划分区域,当bFinish的值为true时就不再进行区域划分,首先对目前的区域进行划分,把每次划分得到的有关键点的子区域设为新的节点,将nToExpand参数加一,并插入到节点列表的前边,删除掉其父节点。只要新节点中的关键点的个数超过一个,就继续划分,继续插入列表前面,继续删除父节点,直到划分的子区域中的关键点的个数是一个,然后迭代器加以移动到下一个节点,继续划分区域。当划分的区域即节点的个数大于关键点的个数或者分裂过程没有增加节点的个数时就将bFinish的值设为true,不再进行划分。如果以上条件没有满足,但是满足((int)lNodes.size()+nToExpand*3)>N,表示再分一次即将结束,所以开始按照特征点的数量对节点进行排序,特征点数多的节点优先划分,知道节点数量满足。vSizeAndPointerToNode 是前面分裂出来的子节点(n1, n2, n3, n4)中可以分裂的节点。按照它们特征点的排序,先从特征点多的开始分裂,分裂的结果继续存储在 lNodes 中。每分裂一个节点都会进行一次判断,如果 lNodes 中的节点数量大于所需要的特征点数量,退出整个 while(!bFinish) 循环,如果进行了一次分裂,并没有增加节点数量,不玩了,退出整个 while(!bFinish) 循环。取出每一个节点(每个区域)对应的最大响应点,即我们确定的特征点。NOTED:因为经过FAST提取出的关键点有很多,当划分的子区域一旦大于mnFeaturesPerLevel[level](根据nfeatures算出的每一个level层最多的特征点数)的时候就不再进行区域划分了,所以每个区域内(节点)的关键点数会很多,取出响应值最大的那个就是我们想要的特征点。这个函数的意义就是根据mnFeaturesPerLevel,即该层的兴趣点数,对特征点进行剔除,根据Harris角点的score进行排序,保留正确的。
经过以上步骤,我们提出来level层在无边界图像中的特征点,并给特征点条件边界补偿及尺度信息。

资源下载

资源下载地址1:https://pan.baidu.com/s/1-85fhVDahlu3ltn_bxqX5Q

相关资源

网友留言