Advertisement

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

阅读量:

今天的笔记内容涉及特征算法中的一个常用方法——ORB特征提取与描述。ORBFature提取与描述的过程分别涵盖了从候选区域筛选出稳定且具有独特特性的关键点,并生成其对应的描述符。在之前的博文中讨论了另一种基于速度梯度检测器(FAST)的快速特征提取方法,在此基础上结合高效的短向量编码器(BRIEF),这一新的处理框架——ORB技术应运而生。它不仅继承了FAST方法在运行时低延迟的优势,并且继承了BRIEF简短编码的特点,在保持计算效率的同时提升了整体性能表现。

该算法基于Oriented FAST和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 Invariant Features)核心方法进行了基础性的拓展与完善。随后,在这一基础上进一步优化了ORB(Oriented FAST and Rotated BRIEF)特性提取机制。特别地,在ORB方法中为了克服传统BRIEF缺乏旋转不变性这一局限性而进行了针对性的设计改进

可以说,在SIFT算法专利生命周期内,ORB特征算法作为一种性能优越的替代方案应运而生;然而随着技术发展,《SIFT algorithm has successfully overcome patent barriers》这一版本已突破专利屏障,《OpenCV 4.3.0 version allows direct application》因此可以直接应用无需额外配置。个人使用的版本为4.2.0,并不打算进行升级。。

该特征提取流程大致可分为以下几个步骤:首先通过FAST算法定位图像中的关键点位置;接着利用Harris算法识别出图像中那些在x和y方向上变化幅度较大的点作为候选特征点;随后将图像经过多尺度金字塔变换处理以增强特征检测效果;之后计算并确定每个关键点所处的位置及其朝向;在此基础上采用BRIEF编码方法生成每个关键点的二进制特征向量;最后通过贪心策略筛选出与目标区域高度相关的像素块区域。

在OpenCV框架内实现了ORBE算法特征检测器的功能封装,在代码片段中通过自适应指针机制实现的auto orb = ORB::create()代码片段能够高效地生成OBR特征检测器指针对象。利用自适应指针特性可实现对返回值类型的自动识别与管理。其中ORBE算法核心创建函数create()的具体参数配置如下:

1、参数nfeatures: 检测到的最大特征点数;
2、参数scaleFactor: 金字塔缩放因子(必须大于1),默认值为1.2;
缩放因子越大,则所需金字塔层级减少但特征匹配精度降低;
缩放因子越接近于1,则需构建更多层级从而提高匹配精度但会降低计算效率;
3、参数nlevels: 图像金字塔层级数目(通常与缩放因子呈反比),默认值为8;
4、参数edgeThreshold: 未检测到特征边界的大小(应与patchSize相近);
5、参数firstLevel: 存储原始图像层次的位置;
如果中间某一层存储了原始图像,则该层之前的所有层级将存储被放大后的图像信息;
6、参数WTA_K: 用于生成定向BRIEF描述子所需的元素个数(默认值为2);
7、参数scoreType: 特征点匹配得分计算方法:
默认采用HARRIS_SCORE(利用Harris算法对得分进行排序并标记最佳特征点);
采用FAST_SCORE则会牺牲部分特征点稳定性但能显著提升计算速度;
8、参数patchSize: BRIEF描述子所基于的空间邻域大小(默认值为31);
9、参数fastThreshold: FAST算法提取关键点时的阈值(默认值为20)。

生成一个ORB特征探测器后,通过调用orb->detectAndCompute()函数来实现对特征点的探测和计算其对应的特征描述子参数。

1、输入图像变量被设定为待检测的对象;
2、掩膜设置变量被配置为与输入图像对应;
3、特征点集合变量被计算为基于KeyPoint数据类型生成;
4、描述特征点集的数据字段被定义为二值化表示形式。

下面看一下代码演示:

复制代码
    	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特征描述子相类的二元特征描述子在配准时可采用NORM_HANMING作为距离度量指标;而对于如SIFT、SURF等非二元特征描述子,则通常建议使用NORM_L2作为距离度量指标,并且可以选择NORM_L1作为备选方案。

对于被进行匹配的一组特征点对,在计算其相互间的配准距离时

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

在这里插入图片描述
在这里插入图片描述

在操作过程中,在对象中分离出' A'元素,并对其进行翻转处理以达到预期效果

在这里插入图片描述

可以看到,在设定特定参数之后, 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:本人笔记种类多且丰富,在个人学习过程中既有自己独特的心得体会也有从网络资源中收集的知识点。因此如有重复出现的情况纯属我对前人学习精神的致敬若有关方面认为我的笔记内容可能存在侵权嫌疑请通过相关途径与我联系我会妥善处理相关事宜并删除涉及的内容深表歉意并致谢!

全部评论 (0)

还没有任何评论哟~