今天要整理记录的笔记内容是特征算法中比较常用的一种——ORB特征提取描述算法,顾名思义,ORB算法包含了对特征点的提取和描述这两个部分。而在上次的博文《OpenCV4学习笔记(39)》中,记录了FAST特征提取算法和BRIEF特征描述算法,而今天的ORB算法正是这两者的融合升级。

ORB(Oriented FAST and Rotated BRIEF)算法是一种快速特征点提取和描述的算法。这个算法是由Ethan Rublee, Vincent Rabaud, Kurt Konolige以及Gary R.Bradski在2011年一篇名为《ORB:An Efficient Alternative to SIFT or SURF》的文章中提出。

ORB算法分为两部分,分别是特征点提取和特征点描述。

特征提取部分是由FAST(Features from Accelerated Segment Test)算法发展来的,特征点描述是根据BRIEF(Binary Robust IndependentElementary Features)特征描述算法改进的。ORB特征是将FAST特征点的检测方法与BRIEF特征描述子结合起来,并在它们原来的基础上做了改进与优化。尤其是对于BRIEF算法,在ORB算法中针对其不具有旋转不变性这个缺点,做了针对性优化。

可以说,ORB特征算法是SIFT算法处于专利保护期时的一个高效替代算法,当然现在的SIFT算法已经过了专利保护了,在OpenCV4.3.0版本中已经能够使用了而且不需要自己编译。(虽然我用的还是4.2.0,懒得下载。。。)

ORB特征提取描述算法的流程大概可以分为以下几部分:
1、基于FAST算法提取关键点;
2、基于Harris算法(寻找在x、y两个方向上都有比较大变化的点,当某点在x和y方向上的二次导数值比较大时,则该点可以认为是特征点)筛选匹配分数高的关键点;
3、对图像进行金字塔变换;
4、计算关键点中心和角度方向;
5、基于BRIEF算法计算关键点的二值描述子;
6、基于贪心算法过滤低相关性像素块。

在OpenCV中封装了ORB算法的特征检测器,我们通过auto orb = ORB::create()来创建OBR特征检测器指针,可以使用auto智能指针来自动判断返回值类型。其中,create()的参数如下:

1、参数nfeatures:检测到的最大特征点数;
2、参数scaleFactor:金字塔缩放比例,是一个大于1的float类型数值,默认值为1.2;
scaleFactor == 2表示经典图像金字塔,每一层图像尺寸是上一层图像尺寸的1/2,但是如此大的缩放比例将大大降低特征匹配分数;
缩放比例越大、所需金字塔层数越少、速度更快、特征点匹配的精度更低,缩放比例越小(越接近1)、所需金字塔层数越多、速度更慢、特征点匹配精度更高;
3、参数nlevels:图像金字塔层数,一般与scaleFactor成反比,默认值为8;
4、参数edgeThreshold:未检测到特征的边框的大小,应该与patchSize参数大致匹配;
5、参数firstLevel:存放原图像的金字塔等级;如果在金字塔中间层存放原图像,则该层前面的金字塔层将会存放原图像的放大图像;
6、参数WTA_K: 产生定向的BRIEF描述子的每个元素的点数,默认值为2;
7、参数scoreType:使用的匹配分数计算方式;默认的HARRIS_SCORE:表示使用Harris算法对特征点的匹配分数进行排序(分数被写入KeyPoint :: score并用于保留最佳特征点);FAST_SCORE:产生的稳定关键点会稍差一些,但计算速度会稍快一些。
8、参数patchSize:计算定向的BRIEF描述子使用的邻域大小;在较高的金字塔层上,特征覆盖的感知图像区域将更大,默认值为31。
9、参数fastThreshold:FAST算法提取特征点的阈值,默认值为20。

创建ORB特征检测器后,使用orb->detectAndCompute()来检测特征点并且计算特征点的特征描述子,其参数含义如下:

1、参数image:输入的待检测图像;
2、参数mask:针对输入图像的掩膜;
3、参数keyPoints:输出的特征点集;是一个KeyPoint类型的向量;
4、参数descriptors:输出的用于描述特征点集的二值描述子。

下面看一下代码演示:

 Mat tem = imread("D:\\opencv_c++\\opencv_tutorial\\data\\images\\a.png");flip(tem, tem, 0);resize(tem, tem, Size(), 1.5, 1.5);Mat test = imread("D:\\opencv_c++\\opencv_tutorial\\data\\images\\abc.png");//创建OBR对象指针,使用auto智能指针来自动判断返回值类型auto orb = ORB::create(100, 1.6, 8, 31, 0, 2, ORB::HARRIS_SCORE, 31, 20);   //通过ORB算法检测两幅图像中的特征点,并计算各自的二值描述子vector<KeyPoint> keyPoints_tem, keyPoints_test;Mat descriptors_tem, descriptors_test;orb->detectAndCompute(tem, Mat(), keyPoints_tem, descriptors_tem, false);orb->detectAndCompute(test, Mat(), keyPoints_test, descriptors_test, false);//特征匹配是通过使用合适的相似度度量比较特征描述子来执行的。//定义特征描述子匹配器Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(DescriptorMatcher::MatcherType::BRUTEFORCE);//参数MatcherType:匹配器类型,这里使用MatcherType::BRUTEFORCE(暴力匹配算法)vector<DMatch> matches;//通过描述子匹配器,对两幅图像的描述子进行匹配,也就是将两幅图像中的对应特征点进行匹配;输出的是一个DMatch结构体向量,其每一个DMatch结构体包含一组对应特征点的信息。matcher->match(descriptors_tem, descriptors_test, matches, Mat());float maxdist = 0;for (int i = 0; i < matches.size(); i++){//寻找匹配特征点对中匹配质量最差的点对,也就是匹配距离最远的点对,获取该最大距离值maxdist = max(maxdist, matches[i].distance);   }vector<DMatch> good_matches;for (int j = 0; j < matches.size(); j++){//如果匹配特征点对中,某个点对的匹配距离小于某个阈值(可以是最大距离值乘以一个小于1的系数),则可以认为是高度匹配的特征点对if (matches[j].distance < 0.18 * maxdist)       {good_matches.push_back(matches[j]);}}//将两幅图像之间的高度匹配的对应特征点使用连线绘制出来,输出一幅将两幅图像拼接起来再进行连线的图像//Scalar::all(-1)是选择随机颜色Mat result;drawMatches(tem, keyPoints_tem, test, keyPoints_test, good_matches, result, Scalar::all(-1), Scalar::all(-1));imshow("result", result);

在上述代码中,对两幅图像进行ORB特征提取和描述,并通过描述子匹配器对两幅图像的描述子进行匹配,也就是将两幅图像中的对应特征点进行匹配,输出的是一个DMatch结构体向量,向量中每一个DMatch结构体包含一组对应特征点的信息。

注意:对于与ORB特征描述子类似的二进制描述子而言,在匹配时采用NORM_HANMING来作为度量距离;而对于类似SIFT、SURF之类的非二进制描述子而言,一般常用NORM_L2作为距离度量,也可以选用NORM_L1

在进行匹配的特征点对中,如果某个点对的匹配距离小于某个阈值(可以是最大距离值乘以一个小于1的系数),则可以认为该点对是高度匹配的特征点对,然后我们就可以将两幅图像之间的高度匹配的对应特征点通过连线绘制出来,并输出一幅将两幅图像拼接起来再进行对应特征点连线的图像。

下面是进行匹配的模板图和匹配图:


这里,我把“A”给抠了出来,而且把它给旋转了180度,并且放大1.5倍,下面看看匹配的结果:


可以看到,ORB算法在设置一定参数后,找到了三个高度匹配的特征点对,通过人眼观察可以判断这些匹配特征点是正确匹配的。也就是说,对于一幅放大且旋转了的模板图,ORB算法也能够提取出效果比较好的特征点。

如果我们不进行匹配,而是想知道特征点的分布和方向,可以将找到的特征点及其方向完全可视化出来,代码演示如下:

 //绘制每幅图像的关键点drawKeypoints(tem, keyPoints_tem, tem, Scalar::all(-1), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);drawKeypoints(test, keyPoints_test, test, Scalar::all(-1), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);//参数flag:DEFAULT:只绘制特征点的坐标点,显示在图像上就是一个个小圆点,每个小圆点的圆心坐标都是特征点的坐标;//                DRAW_OVER_OUTIMG:函数不创建输出的图像, 而是直接在输出图像变量空间绘制, 要求本身输出图像变量是初始化好了;//                NOT_DRAW_SINGLE_POINTS:单独的特征点不被绘制;//              DRAW_RICH_KEYPOINTS:绘制带有方向信息的特征点,用一个带有指向的圆来表示特征点。imshow("tem", tem);imshow("test", test);

看一下效果图:

效果图中,每个特征点绘制出来都是一个圆,而每个圆都带有一条作为指向的半径。

好了,今天关于ORB特征提取描述算法的记录就到此为止,下次的笔记就基于ORB算法提取出的特征描述子来实现图像中的已知目标检测,下次见啦~

PS:本人的注释比较杂,既有自己的心得体会也有网上查阅资料时摘抄下的知识内容,所以如有雷同,纯属我向前辈学习的致敬,如果有前辈觉得我的笔记内容侵犯了您的知识产权,请和我联系,我会将涉及到的博文内容删除,谢谢!

OpenCV4学习笔记(41)——ORB特征提取描述算法相关推荐

  1. OpenCV4学习笔记(47)——BRISK特征提取描述算法

    今天要整理记录的是OpenCV中BRISK特征提取描述算法的运用. BRISK特征提取描述算法全称为 Binary Robust Invariant Scalable Keypoints(二进制鲁棒不 ...

  2. OpenCV4学习笔记(57)——基于GrabCut图像分割算法实现背景替换与背景虚化效果

    在上一篇笔记<OpenCV4学习笔记(56)>中,整理了关于在OpenCV中使用GrabCut图像分割算法的相关内容,那么本次笔记就以GrabCut算法为基础来实现对图像的背景替换和背景虚 ...

  3. OpenCV4学习笔记(55)——基于KNN最近邻算法实现鼠标手写数字识别

    在上一篇博客<OpenCV4学习笔记(54)>中,整理了关于KNN最近邻算法的一些相关内容和一个手写体数字识别的例子.但是上次所实现的手写体数字识别,每次只能固定地输入测试图像进行预测,而 ...

  4. 【C++ Primer 学习笔记】: 容器和算法之【泛型算法】

    本系列博客主要是在学习 C++ Primer 时的一些总结和笔记. [C++ Primer 学习笔记]: 容器和算法之[泛型算法] 本文地址:http://blog.csdn.net/shanglia ...

  5. 小猫爪:i.MX RT1050学习笔记15-FlexSPI-FLASH使用3-KEIL FLASH算法中的使用

    小猫爪:i.MX RT1050学习笔记15-FlexSPI-FLASH使用3-KEIL FLASH算法中的使用 1 前言 2 FLASH算法解析 2.1 初始化Init 2.2 写操作 END 1 前 ...

  6. OPENCV-4 学习笔记

    OPENCV-4 学习笔记 ROI-设定感兴趣的区域(region of interest) 定义: Mat imageROI; //方法一:通过Rect指定矩形区域 imageROI=image(R ...

  7. 机器学习实战(Machine Learning in Action)学习笔记————06.k-均值聚类算法(kMeans)学习笔记...

    机器学习实战(Machine Learning in Action)学习笔记----06.k-均值聚类算法(kMeans)学习笔记 关键字:k-均值.kMeans.聚类.非监督学习 作者:米仓山下 时 ...

  8. 深度学习笔记(10) 优化算法(二)

    深度学习笔记(10) 优化算法(二) 1. Adam 优化算法 2. 学习率衰减 3. 局部最优的问题 1. Adam 优化算法 Adam代表的是 Adaptive Moment Estimation ...

  9. 深度学习笔记(9) 优化算法(一)

    深度学习笔记(9) 优化算法(一) 1. Mini-batch 梯度下降 2. 指数加权平均数 3. 动量梯度下降法 4. 均方根反向传播 1. Mini-batch 梯度下降 把训练样本放大巨大的矩 ...

最新文章

  1. ubuntu 12.04 php升级,在 Ubuntu 12.04 LTS 中将 PHP 从 5.3 升级到 5.5
  2. 分区式存储管理算法实现_穿梭式自动化立体库的种类和特点有哪些?
  3. Linux的三种特殊权限
  4. ajax请求目标地址,AJAX功能目标
  5. java反射api研究_深入研究Java 8中的可选类API
  6. 详解NLP技术中的:预训练模型、图神经网络、模型压缩、知识图谱
  7. python中如何统计元组中元素的个数_python-无论元素顺序如何,获取列表中的元组数...
  8. 用c语言中的函数来求公约数,C语言中求最大公约数的函数
  9. 职业学校计算机知识试卷答案,2016中等职业学校计算机等级考试题库(含答案)计算机基础题库...
  10. 链接oracle 灾难性故障,打开计划任务的时候出现灾难性故障.
  11. String、StringBuilder、StringBuffer 区别
  12. P3089 [USACO13NOV]POGO的牛Pogo-Cow
  13. matlab中如何对一个小数取整,学习笔记153—matlab中小数如何取整?
  14. Gamefi+山海经,流行与古风的结合,带你边玩边赚
  15. 25-Web-京东登录界面
  16. 已会背诵英文文章 How To Boost Your Confidence
  17. 北邮计算机考研专业课分值,北邮计算机考研分数线
  18. 顶级赛事|2021 CCF大数据与计算智能大赛重磅来袭!
  19. java后台将数据导出到Excel表格
  20. 2021第十三届中国最佳酒店大奖榜单揭晓:年度最佳酒店、最佳顶级奢华酒店、最佳城市地标酒店...

热门文章

  1. 不得不服!Chrome 灵魂插件!
  2. 个人博客搭建之网站和邮箱域名解析
  3. 二叉树(Java版)
  4. 模块式浪涌保护器概述和防雷元件解析
  5. 字节跳动再战互联网+教育 , 大数据赋能精准教学有何趋势?
  6. [电脑]_开始着手做小软件站
  7. VsCode反应较慢(vscode卡顿,反应慢)
  8. Java 添加、读取、删除Excel形状
  9. alibaba.jym.item.external.goods.status.batch.query( 交易猫外部商家商品状态批量查询接口 )
  10. Unity 捏脸整理及基于骨骼的捏脸功能实现