ORB-SLAM 解读(一)ORB关键点提取
【课程预定】ORB-SLAM 解读
ORB-SLAM
https://zhuanlan.zhihu.com/p/47451004
https://www.zhihu.com/question/35116055
来自《基于单目视觉的同时定位与地图构建方法综述》
ORB-SLAM 基本延续了 PTAM 的算法框架,但对框架中的大部分组件都做了改进, 归纳起来主要有 4 点:
- ORB-SLAM 选用了 ORB 特征[27], 基于 ORB 描述量的特征匹配和重定位[28], 都比 PTAM具有更好的视角不变性. 此外, 新增三维点的特征匹配效率更高, 因此能更及时地扩展场景. 扩展场景及时与否决定了后续帧是否能稳定跟踪.
- ORB-SLAM 加入了循环回路的检测和闭合机制, 以消除误差累积. 系统采用与重定位相同的方法来检测回路(匹配回路两侧关键帧上的公共点), 通过方位图(Pose Graph)优化来闭合回路.
- PTAM 需要用户指定 2 帧来初始化系统, 2 帧间既要有足够的公共点, 又要有足够的平移量. 平移运动为这些公共点提供视差(Parallax), 只有足够的视差才能三角化出精确的三维位置. ORB-SLAM 通过检测视差来自动选择初始化的 2 帧.
- 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关键点提取相关推荐
- opencv与ORB SLAM提取orb特征点比较
在ORB SLAM中,通过四叉树的方式存储关键点,使得图像上特征点分布均匀,便于追踪.此次实验分别用opencv接口和ORB SLAM实现特征点的提取,效果图如下: 实现程序: #include &l ...
- VSLAM系列原创01讲 | 深入理解ORB关键点提取:原理+代码
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自 | 计算机视觉life ORB特征提取 小白:师兄,OR ...
- SLAM中的 ORB特征检测与匹配(理论篇)
<SLAM十四讲>视觉里程计第一部分的实践便是ORB特征检测 下面来讲讲ORB的理论: ORB算法分为两部分,第一部分是特征提取算法即FAST算法,第二部分是特征描述子BRIEF,BRIE ...
- 高翔orbslam_高翔Slambook第七讲代码解读(特征点提取)
点击蓝色字关注我们! 大家好我是小绿. 作为一个视觉SLAM的入门学徒,高翔的书我看了一遍,视频也跟了一遍,代码在自己的电脑上也跑过,但总觉得跟啥都没学没有太大区别. 于是乎决定开始看代码.由于不是计 ...
- PCL中点云关键点提取
PCL中点云关键点提取 1 关键点概念及相关算法 1.1 NARF关键点 1.2 Harris关键点 1.3 PCL中keypoints模块及类介绍 2 关键点入门级实例解析 2.1 如何从深度图像中 ...
- PCL点云处理与关键点提取
关键点简介 关键点也称为兴趣点,它是 2D 图像或 3D 点云或曲面模型上,可以通过检测标准来获取的具有稳定性.区别性的点集.从技术上来说,关键点的数量比原始点云或图像的数据量少很多,其与局部特征描述 ...
- PCL NARF关键点提取、SIFT关键点提取、Harris关键点提取
一.NARF关键点提取 1.背景 关键点也称为兴趣点,是通过定义检测标准来获取的具有稳定性.区别性的点集.从技术上来说,关键点的数量要比原始点云的数目少很多,与局部特征描述子结合在一起,组成关键点描述 ...
- 关键点提取:face_recognition、疲劳检测、人脸校准、人脸数据库
日萌社 人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新) 人脸识别功能实现的原理介绍与算法介绍 人脸识别:人脸数据集 A ...
- 利用PCL库从点云数据生成深度图像及关键点提取
利用PCL库从点云数据生成生成深度图像及关键点提取 利用PCL库从点云数据生成深度图像及关键点提取 本想利用标准点云数据库分割成若干块,利用标准点云数据生成深度图像作为数据库用来验证算法,目前效果不是 ...
- SLAM--ORB特征点提取--啰里啰嗦的代码解析
#include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/features2d/fea ...
最新文章
- 不止最佳长论文,腾讯AI在ACL上还有这些NLP成果(附论文链接)
- python语言表白源码-表白 - python代码库 - 云代码
- JAVA正则忽略大小写
- java阶乘求和正负交替_C语言程序设计课件第4章090909
- docker之容器数据卷
- CKFinder根据用户设置权限,不同用户有自己的私有的、独立的文件夹
- 一步步学习EF Core(1.DBFirst)
- 无光驱不支持USB设备启动的笔记本,如何使用Ghost来安装系统
- 利用微信实现自动发送监控告警
- indesign照片放入太大_照片打印机,小米、华为到底哪家强?
- 用animation制作走马灯
- 轻松调整,提升写作效率,让 Word 更好地为你所用
- 【大数据实战项目一】数据下载以及工具软件的使用
- 【动手学深度学习】01 Windows下安装环境
- 星空下的新赛点,民营航空迎来新机会
- 谨慎redis的timeout参数
- 便携电源快充方案 30W自动升降压PD快充
- Qt模仿安卓手机中app图标移动
- 科学计算机的圆周率,科学家用超级计算机计算圆周率,到底有什么意义?真能算出来吗?...
- 谈学习中的改变——有病要诊断,有药要服用
热门文章
- 利用ArcGIS Pro进行时空数据挖掘和可视化呈现
- matlab经验正交分解函数EOF的实现—基于Climate Data Toolbox操作
- pip3 install tesserocr安装失败
- 运输层(UDP)详解(一)
- 利用计算机模拟专家给病人,《计算机应用基础2007》复习资料
- 微信小程序开发--【Hello World 及代码结构】(二)
- Google Exoplayer之全面认识
- Android View框架总结(二)View焦点
- 电信公网ip和内网ip的区别_私有IP共有IP和弹性IP的区别
- php 中tp3.2中c,thinkphp3.2笔记(2)调试模式,配置项C,创建模块, 四种URL模式,URL生成,跳转...