【课程预定】ORB-SLAM 解读

ORB-SLAM

https://zhuanlan.zhihu.com/p/47451004

https://www.zhihu.com/question/35116055

来自《基于单目视觉的同时定位与地图构建方法综述》

ORB-SLAM 基本延续了 PTAM 的算法框架,但对框架中的大部分组件都做了改进, 归纳起来主要有 4 点:

  1. ORB-SLAM 选用了 ORB 特征[27], 基于 ORB 描述量的特征匹配和重定位[28], 都比 PTAM具有更好的视角不变性. 此外, 新增三维点的特征匹配效率更高, 因此能更及时地扩展场景. 扩展场景及时与否决定了后续帧是否能稳定跟踪.
  2. ORB-SLAM 加入了循环回路的检测和闭合机制, 以消除误差累积. 系统采用与重定位相同的方法来检测回路(匹配回路两侧关键帧上的公共点), 通过方位图(Pose Graph)优化来闭合回路.
  3. PTAM 需要用户指定 2 帧来初始化系统, 2 帧间既要有足够的公共点, 又要有足够的平移量. 平移运动为这些公共点提供视差(Parallax), 只有足够的视差才能三角化出精确的三维位置. ORB-SLAM 通过检测视差来自动选择初始化的 2 帧.
  4. PTAM 扩展场景时也要求新加入的关键帧提供足够的视差, 导致场景往往难以扩展. ORB-SLAM 采用一种更鲁棒的关键帧和三维点的选择机制——先用宽松的判断条件尽可能及时地加入新的关键帧和三维点, 以保证后续帧的鲁棒跟踪; 再用严格的判断条件删除冗余的关键帧和不稳定的三维点, 以保证 BA 的效率和精度. 。

文章目录

  • ORB关键点提取

ORB关键点提取

https://mp.weixin.qq.com/s/qy8lz5N6kRZ2k2TMw0gzuw
https://blog.csdn.net/zfjBIT/article/details/91416757

ORB(Oriented FAST and Rotated BRIEF)特征点出自美国的Willow Garage公司在2012年发表的一篇论文,题目为“ORB: an efficient alternative to SIFT or SURF”。ORB-SLAM整个框架确实得益于该特征点,下面我们就来具体了解一下ORB。

ORB特征

师兄:我们知道特征点是由关键点(keypoint)和描述子(descriptor)两部分组成的。关键点是指该特征点在图像中的位置,有些还包括方向、大小等信息。而描述子是用来量化描述该关键点周围的像素信息的,这里的量化一般是人为设计的某种方式,设计的原则就是“外观相似的特征应该具有相似的描述子”,这样我们想要判断两个不同位置的关键点是否相似,就可以通过计算他们之间描述子的距离来确定了。

小白:那ORB特征点也有关键点和描述子咯?

师兄:是的。ORB的关键点是在FAST(Features from Accelerated Segments Test)关键点基础上进行了改进,主要是增加了特征点的主方向,称之为Oriented FAST。描述子是在BRIEF(Binary Robust Independent Elementary Features)描述子基础上加入了上述方向信息,称之为Rotated BRIEF。

关键点 Oriented FAST

FAST角点
师兄:我们先来了解一下FAST关键点,它是一种检测角点的方法。和它的英文缩写意义一样,FAST确定关键点的速度非常快。
小白:请问什么是角点呢?
师兄:我们前面提到的特征点其实是图像里一些比较特殊的地方。我们可以大致分为3类:平坦区域、边缘和角点。如下图所示。我们在图像中取一个小窗口来判断局部区域的类型。从图中可以看到,左边平坦区域内部沿所有方向灰度都是没有变化的;而中间的边缘沿水平方向灰度是有变化的,但是垂直方向没有变化;右边的角点则沿所有方向都有灰度变化。这个角点就是图像中有辨识度的点。而FAST就是一种高效的角点判定方法。


小白:那FAST也要这样用一个窗口来统计里面所有像素灰度的变化吗?
师兄:不需要,那样太慢了。FAST的思想是这样的:如果一个像素和它周围的像素灰度差别较大(超过设定的阈值),并且达到一定的数目,那么这个像素很可能就是角点。具体检测过程如下:


此外,由于FAST关键点很容易扎堆出现,所以第一次遍历完图像后还需要用到非极大值抑制,在一定范围内保留响应值最大的作为该范围内的FAST关键点。

为什么需要图像金字塔?
小白:根据上面的描述,FAST固定选取的是半径为3的圆,那这个关键点是不是就和相机拍摄物体的分辨率有关了?如下图所示,我在初始位置(下图(a)中 Original position)通过FAST-9判定是关键点,但是当相机靠近物体进行拍摄(下图(b)中 Forward),此时这个角点占用的像素数目就会变多,固定的半径3的圆就检测不到角点了?或者当相机远离物体进行拍摄(下图(c)中 Backward),此时这个角点占用的像素数目就会变少,固定的半径3的圆也检测不到角点?


师兄:是的,这个就是FAST存在的问题,我们称之为尺度问题,ORB特征点使用图像金字塔来确保特征点的尺度不变性。图像金字塔是计算机视觉领域中常用的一种方法。如下图所示,金字塔底层是原始图像,在ORB-SLAM2里对应的金字塔层级是。每往上一层,就对图像做一个固定倍率的缩放,得到不同分辨率的图像。在提取ORB特征点的时候,我们会在每一个金字塔层级上进行特征提取,这样不管相机拍摄距离物体是远还是近,我们可以在某个金字塔层级提取到真正的角点。我们在对不同图像特征点进行特征匹配时,就可以匹配不同图像里不同层级的金字塔上提取的特征点,实现尺度不变性。


旋转不变性

小白:原来如此。那么ORB特征点的旋转不变性是怎么实现的呢?
师兄:所谓旋转不变性,思路也比较直观,就是先想办法计算每个关键点的“主方向”,然后统一将像素旋转到这个“主方向”,这样就使得每个特征点的描述子不受旋转的影响了。
小白:那怎么计算关键点的“主方向”呢?
师兄:我们使用灰度质心(Intensity Centroid)法来计算关键点的“主方向”。这里的灰度质心就是一个图像区域内像素灰度值作为权重的中心,是需要我们计算的。这里的图像区域一般是圆形区域,在ORB-SLAM2里面设定的是直径为31的圆形。这个圆形的圆心叫做形心,也就是几何中心。这个形心指向质心的向量就代表这个关键点的“主方向”

灰度质心(Intensity Centroid)法来计算关键点的“主方向”
下面重点说一下如何计算灰度质心。

ORB-SLAM2代码实现时,使用了一些技巧来加速计算灰度质心。下面讲一下背后的原理和流程。

/*** @brief 这个函数用于计算特征点的方向,这里是返回角度作为方向。* 计算特征点方向是为了使得提取的特征点具有旋转不变性。* 方法是灰度质心法:以几何中心和灰度质心的连线作为该特征点方向* @param[in] image     要进行操作的某层金字塔图像* @param[in] pt        当前特征点的坐标* @param[in] u_max     图像块的每一行的坐标边界 u_max* @return float        返回特征点的角度,范围为[0,360)角度,精度为0.3°*/
static float IC_Angle(const Mat& image, Point2f pt,  const vector<int> & u_max)
{//图像的矩,前者是按照图像块的y坐标加权,后者是按照图像块的x坐标加权int m_01 = 0, m_10 = 0;//获得这个特征点所在的图像块的中心点坐标灰度值的指针centerconst uchar* center = &image.at<uchar> (cvRound(pt.y), cvRound(pt.x));//这条v=0中心线的计算需要特殊对待//由于是中心行+若干行对,所以PATCH_SIZE应该是个奇数for (int u = -HALF_PATCH_SIZE; u <= HALF_PATCH_SIZE; ++u)//注意这里的center下标u可以是负的!中心水平线上的像素按x坐标(也就是u坐标)加权m_10 += u * center[u];//这里的step1表示这个图像一行包含的字节总数int step = (int)image.step1();//注意这里是以v=0中心线为对称轴,然后对称地每成对的两行之间进行遍历,这样处理加快了计算速度for (int v = 1; v <= HALF_PATCH_SIZE; ++v){// Proceed over the two lines//本来m_01应该是一列一列地计算的,但是由于对称以及坐标x,y正负的原因,可以一次计算两行int v_sum = 0;// 获取某行像素横坐标的最大范围,注意这里的图像块是圆形的!int d = u_max[v];//在坐标范围内挨个像素遍历,实际是一次遍历2个// 假设每次处理的两个点坐标,中心线下方为(x,y),中心线上方为(x,-y) // 对于某次待处理的两个点:m_10 = Σ x*I(x,y) =  x*I(x,y) + x*I(x,-y) = x*(I(x,y) + I(x,-y))// 对于某次待处理的两个点:m_01 = Σ y*I(x,y) =  y*I(x,y) - y*I(x,-y) = y*(I(x,y) - I(x,-y))for (int u = -d; u <= d; ++u){//得到需要进行加运算和减运算的像素灰度值//val_plus:在中心线下方x=u时的的像素灰度值//val_minus:在中心线上方x=u时的像素灰度值int val_plus = center[u + v*step], val_minus = center[u - v*step];//在v(y轴)上,2行所有像素灰度值之差v_sum += (val_plus - val_minus);//u轴(也就是x轴)方向上用u坐标加权和(u坐标也有正负符号),相当于同时计算两行m_10 += u * (val_plus + val_minus);}//将这一行上的和按照y坐标加权m_01 += v * v_sum;}//为了加快速度还使用了fastAtan2()函数,输出为[0,360)角度,精度为0.3°return fastAtan2((float)m_01, (float)m_10);
}

综上:
ORB特征是将FAST特征点的检测方法与BRIEF特征描述子结合起来,并在它们原来的基础上做了改进与优化:

  • 使用非最大值抑制,在一定区域内仅仅保留响应极大值的角点,避免FAST提取到的角点过于集中。FAST提取到的角点数量过多且不是很稳定,ORB中可以指定需要提取到的角点的数量N,然后对FAST提取到的角点分别计算Harris响应值,选择前N个具有最大响应值的角点作为最终提取到的特征点集合。
  • FAST提取到的角点不具有尺度信息,在ORB中使用图像金字塔,并且在每一层金字塔上检测角点,以此来保持尺度的不变性
  • FAST提取到的角点不具有方向信息,在ORB中使用灰度质心法(Intensity Centroid)来保持特征的旋转不变性。

其中:

(1)FAST Features From Accelerated Segment Test 以速度快而著称,检测局部像素灰度变化明显的地方。(SIFT和SURF算法都包含有各自的特征点描述子的计算方法),FAST 不包含特征点描述子的计算,仅仅只有特征点的提取方法,这就需要一个特征点描述方法来描述FAST提取到的特征点,以方便特征点的匹配。使用了专门的特征点描述子的计算算法。

(2) BRIEF描述子

BRIEF是一种二进制的描述子,其描述向量是0和1表示的二进制串。0和1表示特征点邻域内两个像素(p和q)灰度值的大小:如果p比q大则选择1,反正就取0。在特征点的周围选择128对这样的p和q的像素对,就得到了128维由0,1组成的向量。那么p和q的像素对是怎么选择的呢?通常都是按照某种概率来随机的挑选像素对的位置。
BRIEF使用随机选点的比较,速度很快,而且使用二进制串表示最终生成的描述子向量,在存储以及用于匹配的比较时都是非常方便的,其和FAST的搭配起来可以组成非常快速的特征点提取和描述算法。

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;int main()
{//0读取图像Mat img1 = imread("..\\image\\left.jpg",0);Mat img2 = imread("..\\image\\right.jpg",0);// 1 初始化特征点和描述子,ORBstd::vector<KeyPoint> keypoints1, keypoints2;Mat descriptors1, descriptors2;Ptr<ORB> orb = ORB::create();// 2 提取 Oriented FAST 特征点orb->detect(img1, keypoints1);orb->detect(img2, keypoints2);// 3 根据角点位置计算 BRIEF 描述子orb->compute(img1, keypoints1, descriptors1);orb->compute(img2, keypoints2, descriptors2);// 4 对两幅图像中的BRIEF描述子进行匹配,使用 Hamming 距离vector<DMatch> matches;BFMatcher bfmatcher(NORM_HAMMING);bfmatcher.match(descriptors1, descriptors2, matches);// 5 匹配对筛选double min_dist = 1000, max_dist = 0;// 找出所有匹配之间的最大值和最小值for (int i = 0; i < descriptors1.rows; i++){double dist = matches[i].distance;//汉明距离在matches中if (dist < min_dist) min_dist = dist;if (dist > max_dist) max_dist = dist;}// 当描述子之间的匹配大于2倍的最小距离时,即认为该匹配是一个错误的匹配。// 但有时描述子之间的最小距离非常小,可以设置一个经验值作为下限vector<DMatch> good_matches;for (int i = 0; i < descriptors1.rows; i++){if (matches[i].distance <= max(2 * min_dist, 30.0))good_matches.push_back(matches[i]);}// 6 绘制匹配结果Mat img_match;drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_match);return 0;
}

ORB-SLAM 解读(一)ORB关键点提取相关推荐

  1. opencv与ORB SLAM提取orb特征点比较

    在ORB SLAM中,通过四叉树的方式存储关键点,使得图像上特征点分布均匀,便于追踪.此次实验分别用opencv接口和ORB SLAM实现特征点的提取,效果图如下: 实现程序: #include &l ...

  2. VSLAM系列原创01讲 | 深入理解ORB关键点提取:原理+代码

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自 | 计算机视觉life ORB特征提取 小白:师兄,OR ...

  3. SLAM中的 ORB特征检测与匹配(理论篇)

    <SLAM十四讲>视觉里程计第一部分的实践便是ORB特征检测 下面来讲讲ORB的理论: ORB算法分为两部分,第一部分是特征提取算法即FAST算法,第二部分是特征描述子BRIEF,BRIE ...

  4. 高翔orbslam_高翔Slambook第七讲代码解读(特征点提取)

    点击蓝色字关注我们! 大家好我是小绿. 作为一个视觉SLAM的入门学徒,高翔的书我看了一遍,视频也跟了一遍,代码在自己的电脑上也跑过,但总觉得跟啥都没学没有太大区别. 于是乎决定开始看代码.由于不是计 ...

  5. PCL中点云关键点提取

    PCL中点云关键点提取 1 关键点概念及相关算法 1.1 NARF关键点 1.2 Harris关键点 1.3 PCL中keypoints模块及类介绍 2 关键点入门级实例解析 2.1 如何从深度图像中 ...

  6. PCL点云处理与关键点提取

    关键点简介 关键点也称为兴趣点,它是 2D 图像或 3D 点云或曲面模型上,可以通过检测标准来获取的具有稳定性.区别性的点集.从技术上来说,关键点的数量比原始点云或图像的数据量少很多,其与局部特征描述 ...

  7. PCL NARF关键点提取、SIFT关键点提取、Harris关键点提取

    一.NARF关键点提取 1.背景 关键点也称为兴趣点,是通过定义检测标准来获取的具有稳定性.区别性的点集.从技术上来说,关键点的数量要比原始点云的数目少很多,与局部特征描述子结合在一起,组成关键点描述 ...

  8. 关键点提取:face_recognition、疲劳检测、人脸校准、人脸数据库

    日萌社 人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新) 人脸识别功能实现的原理介绍与算法介绍 人脸识别:人脸数据集 A ...

  9. 利用PCL库从点云数据生成深度图像及关键点提取

    利用PCL库从点云数据生成生成深度图像及关键点提取 利用PCL库从点云数据生成深度图像及关键点提取 本想利用标准点云数据库分割成若干块,利用标准点云数据生成深度图像作为数据库用来验证算法,目前效果不是 ...

  10. SLAM--ORB特征点提取--啰里啰嗦的代码解析

    #include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/features2d/fea ...

最新文章

  1. 不止最佳长论文,腾讯AI在ACL上还有这些NLP成果(附论文链接)
  2. python语言表白源码-表白 - python代码库 - 云代码
  3. JAVA正则忽略大小写
  4. java阶乘求和正负交替_C语言程序设计课件第4章090909
  5. docker之容器数据卷
  6. CKFinder根据用户设置权限,不同用户有自己的私有的、独立的文件夹
  7. 一步步学习EF Core(1.DBFirst)
  8. 无光驱不支持USB设备启动的笔记本,如何使用Ghost来安装系统
  9. 利用微信实现自动发送监控告警
  10. indesign照片放入太大_照片打印机,小米、华为到底哪家强?
  11. 用animation制作走马灯
  12. 轻松调整,提升写作效率,让 Word 更好地为你所用
  13. 【大数据实战项目一】数据下载以及工具软件的使用
  14. 【动手学深度学习】01 Windows下安装环境
  15. 星空下的新赛点,民营航空迎来新机会
  16. 谨慎redis的timeout参数
  17. 便携电源快充方案 30W自动升降压PD快充
  18. Qt模仿安卓手机中app图标移动
  19. 科学计算机的圆周率,科学家用超级计算机计算圆周率,到底有什么意义?真能算出来吗?...
  20. 谈学习中的改变——有病要诊断,有药要服用

热门文章

  1. 利用ArcGIS Pro进行时空数据挖掘和可视化呈现
  2. matlab经验正交分解函数EOF的实现—基于Climate Data Toolbox操作
  3. pip3 install tesserocr安装失败
  4. 运输层(UDP)详解(一)
  5. 利用计算机模拟专家给病人,《计算机应用基础2007》复习资料
  6. 微信小程序开发--【Hello World 及代码结构】(二)
  7. Google Exoplayer之全面认识
  8. Android View框架总结(二)View焦点
  9. 电信公网ip和内网ip的区别_私有IP共有IP和弹性IP的区别
  10. php 中tp3.2中c,thinkphp3.2笔记(2)调试模式,配置项C,创建模块, 四种URL模式,URL生成,跳转...