点击上方“小白学视觉”,选择加"星标"或“置顶”
重磅干货,第一时间送达
本文转自 | 计算机视觉life

ORB特征提取

小白:师兄,ORB-SLAM我一直都有听过,ORB应该是一种特征点,这个开源算法能够用ORB这种特征点命名,一定是因为这种特征点具有非常大的优势吧?

师兄:没错。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的思想是这样的:如果一个像素和它周围的像素灰度差别较大(超过设定的阈值),并且达到一定的数目,那么这个像素很可能就是角点。具体检测过程如下:

  • 第1步:在图像中选择某个像素,它的灰度值记为。

  • 第2步:设定一个阈值,用于判断两个像素灰度值差异大小,为了能够自适应不同的图像,一般采用相对百分比例,比如设置为的20%。

  • 第3步:以像素为中心,选取半径为3的圆上的16个像素点。选取方式见下图右所示。

  • 第4步:如果16个像素点中有连续的个点的灰度大于或者小于,那么可以将像素确定为关键点。在ORB的论文中,作者说时效果较好,称之为FAST-9。实际操作中为了加速,我们可以把第1,5,9,13个像素点当做锚点,在FAST-9算法中,只有当这4个锚点中有3个及以上灰度值同时大于或者小于,当前像素才可能是一个关键点进入到下一个阶段的判断,否则就可以排除掉,这大大加速了关键点检测的速度。

  • 第5步:遍历图像中每个像素点,循环执行以上四个步骤。

此外,由于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的圆形。这个圆形的圆心叫做形心,也就是几何中心。这个形心指向质心的向量就代表这个关键点的“主方向”。

下面重点说一下如何计算灰度质心。

  • 第1步:我们定义该区域图像的矩为:

    式中,取0或者1,,表示在像素坐标处图像的灰度值,表示图像的矩。

    在半径为的圆形图像区域,沿两个坐标轴方向的图像矩分别为:

    圆形区域内所有像素的灰度值总和为:

  • 第2步:图像的质心为:

  • 第3步:然后关键点的“主方向”就可以表示为从圆形图像形心指向质心的方向向量,于是关键点的旋转角度记为

以上是灰度质心法求关键点旋转角度的原理。

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

  • 第1步:我们要处理的是一个圆形图像区域,而圆形是具有对称性的,加速的原理就是根据对称性一次索引多行像素。因此首先我们把索引基准点放在圆形的中心像素点,记为。

  • 第2步:圆形半径记为,先计算圆形区域内水平坐标轴上的一行像素灰度(下图中红色区域),对应的坐标范围是,这一行对应的图像矩分别为:

  • 第3步:然后以水平坐标轴为对称轴,一次性索引与水平轴上下对称的两行像素(下图中绿色区域),上下某两个对称的像素分别记为:

    则这两个点对应的图像矩分别为:

    最后累加即可。


/*** @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);
}

(左右滑动看完整代码)

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目52讲

在「小白学视觉」公众号后台回复:Python视觉实战项目即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲

在「小白学视觉」公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~

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

  1. VSLAM系列原创04讲 | 四叉树实现ORB特征点均匀化分布:原理+代码

    本文系ORB-SLAM2原理+代码实战系列原创文章,对应的视频课程见: 如何真正搞透视觉SLAM? 大家好,从今天开始我们陆续更新ORB-SLAM2/3系列的原创文章,以小白和师兄对话的形式阐述背景原 ...

  2. YOLO系列算法精讲:从yolov1至yolov5的进阶之路(2万字超全整理)

    写在前面:大家好!我是[AI 菌],算法工程师一枚,2021年博客之星Top12,公众号[AI 修炼之路]作者.专注于计算机视觉.深度学习.图像处理技术,热衷于分享AI.CV.DL.ML.OpenCV ...

  3. JVM基础系列第7讲:JVM 类加载机制

    当 Java 虚拟机将 Java 源码编译为字节码之后,虚拟机便可以将字节码读取进内存,从而进行解析.运行等整个过程,这个过程我们叫:Java 虚拟机的类加载机制.JVM 虚拟机执行 class 字节 ...

  4. JVM基础系列第14讲:JVM参数之GC日志配置

    说到 Java 虚拟机,不得不提的就是 Java 虚拟机的 GC(Garbage Collection)日志.而对于 GC 日志,我们不仅要学会看懂,而且要学会如何设置对应的 GC 日志参数.今天就让 ...

  5. 《zw版·Halcon-delphi系列原创教程》halconxlib控件列表

    <zw版·Halcon-delphi系列原创教程>halconxlib控件列表 Halcon v11.01版,com控件,安装后,共有75个控件,       不过最重要的控件,只有两个, ...

  6. 《zw版·Halcon-delphi系列原创教程》 Halcon分类函数014,tuple,元组

    <zw版·Halcon-delphi系列原创教程> Halcon分类函数014,tuple,元组 为方便阅读,在不影响说明的前提下,笔者对函数进行了简化: :: 用符号"**&q ...

  7. 智能科学技术导论周昌乐答案_智能科学技术导论-周乐昌-第01讲 引论

    智能科学技术导论 周昌乐教授教学课件 dozero@xmu.edu.cn www.bliss.xmu.edu.cn 第 01 讲引论 主讲 : 周昌乐教授 福建省仿脑智能系统重点实验室 厦门大学智能科 ...

  8. 计算机软件与应用ppt,【第01讲Rup与敏捷_计算机软件及应用_IT计算机_专业-精品课件PPT材料】...

    第01讲Rup与敏捷_计算机软件及应用_IT计算机_专业资料-精品课件(PPT) <第01讲Rup与敏捷_计算机软件及应用_IT计算机_专业资料-精品课件(PPT).ppt>由会员分享,可 ...

  9. 《zw版·Halcon-delphi系列原创教程》 Halcon分类函数011,ocr,字符识别

    <zw版·Halcon-delphi系列原创教程> Halcon分类函数011,ocr,字符识别 为方便阅读,在不影响说明的前提下,笔者对函数进行了简化: :: 用符号"**&q ...

最新文章

  1. 给你一个团队怎么带?抓住3要点,别做13件事,没人敢不服你
  2. 在RHEL5.0中用YUM解决RPM包的依赖关系
  3. systemctl 命令完全指南
  4. bashrc, bash_profile etc;
  5. 【数据结构与算法】之深入解析“复制带随机指针的链表”的求解思路与算法示例
  6. 【转载】KMP算法详解
  7. Nike Hyperdunk 2012 Men's Basketball Shoes Black/Gorge Green
  8. 从底部上滑失灵_iPad 上这 20 个快捷操作,真正帮你提高生产力!
  9. JSON.parse 和 JSON.stringify
  10. 【CVPR 2021】VarifocalNet: An IoU-aware Dense Object Detector的译读笔记
  11. 120万名 GoDaddy 客户数据遭泄露
  12. 2.程序员的自我修养---编译和链接
  13. ATFX:美国通胀转折点已来,激进加息势将暂缓?
  14. seo需要编程技术吗?学黑帽seo需要什么技术?
  15. Gambler Bo
  16. JVM:垃圾收集器与内存分配策略
  17. 一键合并多个Excel文档
  18. 微信支付V3-企业转账至零钱1/2
  19. Swoole进阶——02 内存之Table
  20. java递归处理单位人员组织机构树

热门文章

  1. 知识图谱升温之势已现,不要错失下一个AI风口
  2. 人工智能时代,开发者是逆袭还是走向末日?
  3. 是时候装逼了,试试 IDEA 解决 Maven 依赖冲突的高能神器!
  4. 教你如何通过分析GC日志来进行JVM调优
  5. Windows 给力!可以扔掉 Linux 虚拟机了!
  6. Datawhale浙大分享(附投票结果)
  7. 字节跳动AI Lab 再失大将!大牛王长虎被爆已离职回归学界!
  8. 第四范式申请港交所上市:2021上半年营收7.88亿,研发费用占七成
  9. 基于深度卷积神经网络的小样本分割算法综述
  10. 解决不了bug先放着,这里有40条提升编程技能小妙招