三维重构学习笔记(4):坚实的后盾OpenCV(ORB)
ORB特征提取、匹配
ORB(Oriented FAST and Rotated BRIEF)是一种局部不变特征,从名字可以看出ORB具有FAST和旋转不变的特性。相比于经典的SIFT、SURF,ORB具备了实时使用能力。我的三维重构任务对于实时性具有较高的要求,且三维重构的最为重要的任务就是如何找到对应的特征点,所以ORB如何应用值得好好研究一下。
ORB的介绍看这里,对于ORB的介绍我不再进行过多的说明,本博客主要看看OpenCV中与ORB相关的库函数是如何应用的。
ORB特征的提取
已知对于ORB特征的描述主要包括两个部分:特征点(keypoint),描述(descriptor)。一般定义为:
vector<KeyPoint> key_points;
Mat descriptor;
而目前我见到的创建ORB的特征对象的方式有三种,如:
Ptr<ORB> orb = ORB::create();
或者:
Ptr<FeatureDetector> orb1 = ORB::create();
Ptr<DescriptorExtractor> orb2 = ORB::create();
上述三种声明的意义是一样的,无论是FeatureDetector
还是DescriptorExtractor
都是类Feature2D
的别名。而类ORB
是类Feature2D
的公有继承。具体OpenCV中的定义如下:
typedef Feature2D FeatureDetector;
typedef Feature2D DescriptorExtractor;
class CV_EXPORTS_W ORB : public Feature2D{}
所以无论哪种声明本质上都是一样的,可能ORB类中存在别的函数实现。类的别名主要是为了开发方便。
声明了Feature2D
的对象之后,就可以直接调用detect
和compute
或者detectAndCompute
进行计算“重要的” keypoint 和descriptor了。
计算方式有两种:
//分开计算
orb->detect(img, key_points);
orb->compute(img, key_points, descriptor);
//一起计算
orb->detectAndCompute(img, noArray(),key_points, descriptor);
至此ORB特征提取完毕。
ORB特征匹配
匹配器matcher
声明与ORB特征对象声明一样也存在多种声明方式如:
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");
或者:
BFMatcher matcher(NORM_L2);
在OpenCV中我们发现BFMatcher
是DescriptorMatcher
的公有继承:
class CV_EXPORTS_W BFMatcher : public DescriptorMatcher{}
这样上述不同的matcher
声明就容易理解了。
匹配器matcher
是用于计算特征点的匹配情况的,而计算的结果通常保存在vector<DMatch> matches
中。
匹配函数的调用如下:
matcher->match(descriptor1, descriptor2, matches);
其中descriptor1, descriptor2
分别代表两张不同的图片的特征点(descriptor用于描述特征点),matches
中保存匹配信息。
此时matches
中保存的匹配点中存在匹配不准确的情况,为了提高匹配的精度,通常需要对这些匹配点进行筛选。筛选的方式多种多样,但基本思想都是保留distance满足一定条件的点对,例如:
找出匹配点之间的最大距离和最小距离,也就是匹配最相似和最不相似的点对。选择一个点对的距离阈值对点对进行筛选。
double min_dist = 10000, max_dist = 0;
//查找距离最小和距离最大的点
for (int i = 0; i < query.rows; i++)
{double dist = matches[i].distance;if (dist < min_dist) min_dist = dist;if (dist > max_dist) max_dist = dist;
}std::vector< DMatch > good_matches;
//对匹配的点对进行筛选
for (int i = 0; i < query.rows; i++)
{if (matches[i].distance <= max(2 * min_dist, 30.0)){good_matches.push_back(matches[i]);}
}
good_matches.swap(matches);
或者:
对在knnMatch
中得到的knn_matches
的筛选时,除了distance不能过大,还需要考虑Ratio test(KNN为特征点保留了两个待选匹配点,第一匹配点与第二匹配点的比,越接近1,匹配点越模糊,则被排除)。
vector<vector<DMatch>> knn_matches;BFMatcher matcher(NORM_L2);matcher.knnMatch(query, train, knn_matches, 2);//获取满足Ratio Test的最小匹配的距离float min_dist = FLT_MAX;for (int r = 0; r < knn_matches.size(); ++r){//Ratio Testif (knn_matches[r][0].distance > 0.6*knn_matches[r][1].distance)continue;float dist = knn_matches[r][0].distance;if (dist < min_dist) min_dist = dist;}matches.clear();for (size_t r = 0; r < knn_matches.size(); ++r){//排除不满足Ratio Test的点和匹配距离过大的点if (knn_matches[r][0].distance > 0.6*knn_matches[r][1].distance ||knn_matches[r][0].distance > 5 * max(min_dist, 10.0f))continue;//保存匹配点matches.push_back(knn_matches[r][0]);}
对匹配点进行筛选之后,就解决了三维重构中最为棘手的问题。
tips:
在匹配ORB特征时,我发现网上一般使用的筛选方式都是基于距离的。从我的仿真实验中发现,由于ORB检测到的匹配点较少,使用距离筛选ORB匹配点较为合理,因为使用KNN的方式排除的特征点对较多,导致我的匹配结果无法正常使用SFM三维重构。
三维重构学习笔记(4):坚实的后盾OpenCV(ORB)相关推荐
- 三维重构学习笔记(3):坚实的后盾 OpenCV3
三维重构学习笔记(3):坚实的后盾+OpenCV3 前面两篇笔记分别记录了关于三维重构中,有关相机标定.SFM流程的问题.除了公式的推倒和理解,仿真时始终仰仗OpenCV3大法,为了以后学习使用方便, ...
- 基于结构光的三维测量学习笔记
基于结构光的三维测量学习笔记 1.几种比较成熟的方法 1.1飞行时间发 原理:通过直接测量光传播的时间,确定物体的面型.发射脉冲信号,接受发射回的光,计算距离. 精度:毫米级 优点:原理简单,可避免阴 ...
- 步步为营 .NET 代码重构学习笔记 九
步步为营 .NET 代码重构学习笔记系列 步步为营 .NET 代码重构学习笔记 一.为何要代码重构 步步为营 .NET 代码重构学习笔记 二.提炼方法(Extract Method) 步步为营 .NE ...
- 步步为营 .NET 代码重构学习笔记 十一
步步为营 .NET 代码重构学习笔记系列 步步为营 .NET 代码重构学习笔记 一.为何要代码重构 步步为营 .NET 代码重构学习笔记 二.提炼方法(Extract Method) 步步为营 .NE ...
- 31 天重构学习笔记索引
由于最近在做重构的项目,所以对重构又重新进行了一遍学习和整理,对31天重构最早接触是在2009年10月份,由于当时没有订阅Sean Chambers的blog,所以是在国外的社区上闲逛的时候链接过去的 ...
- 31天重构学习笔记下载
前言 前两天写了一篇程序猿也爱学英语(上),有图有真相的文章,写作那篇文章只是自己一时兴起,或者说是自己的兴趣使然.文中的观点只是自己的学习心得和体会,属一家之言且鉴于本人不是学英语出身,所以也肯定有 ...
- 步步为营 .NET 代码重构学习笔记 十
步步为营 .NET 代码重构学习笔记系列 步步为营 .NET 代码重构学习笔记 一.为何要代码重构 步步为营 .NET 代码重构学习笔记 二.提炼方法(Extract Method) 步步为营 .NE ...
- Java 3D编程实践_Java 3D编程实践——网络上的三维动画[学习笔记]
评论 # re: Java 3D编程实践--网络上的三维动画[学习笔记] 2006-08-24 23:41 gy # re: Java 3D编程实践--网络上的三维动画[学习笔记] 2007-03-2 ...
- UE4蓝图制作三维弹球学习笔记(二)
UE4蓝图制作三维弹球学习笔记(二) 1.BP_Fliper Viewport 使用Static Mesh导入Fliper. Construction 使用同一个蓝图表示左右不同的Fliper.在蓝图 ...
最新文章
- MySQL几个特别语法示例
- 【Python】Python3中的str和bytes
- mfcc中的fft操作_简化音频数据:FFT,STFT和MFCC
- JavaScript与JSP区别
- oracle数据库基础知识总结,oracle数据库基础知识学习笔记
- Linux内存映射实现框架
- ImportError:cannot import name 'distribute_covar_matrix_to_match_covariance_type'
- Fedora 30 将默认启用 DNF-best 模式
- VSCode猜测字符编码
- java中级程序员全面学习路线教程
- 前端开发3年计划,前端应届生如何做一个职业规划
- 第十二天内容《基础交换十二》
- 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十四)具体单板的GPIO操作方法
- Contest 20140914 Mushroom写情书 字符串雙hash 後綴數組
- Win10 计算机扩展显示器闪黑屏
- 爬虫常见的加密解密算法
- 肌电信号的包络matlab程序_基于matlab的肌电信号处理程序:
- 国产“芯”时代 盘点国内十大IC卡制卡企业
- 智创云享知识付费V2 v2.0.9
- 服务器意外终止连接,错误号:0X800CCCOF 如何解决