三维重构学习笔记(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.在蓝图 ...
最新文章
- wxWidgets搜索事件处理函数顺序
- 机器人也来玩“踢瓶盖挑战”了,你动他就动,靠脑电控制,路人也能玩丨MIT出品...
- usb协议规范_你想了解的USB知识,都在这里了!
- Debian 和Ubuntu Mono 3.0 部署包
- JSP、EL和JSTL-学习笔记01【JSP基础语法】
- python定义一个整数变量_python循环定义多个变量的实例分析
- python解释器把python代码一次性翻译成目标代码_Python语言程序设计----【第1周 Python基本语法元素】之1.1 程序设计基本方法...
- 进击的程序媛:毕业于斯坦福,Google 元老级员工,曾任雅虎 CEO | 人物志
- Spring Boot 2.x 把 Guava 干掉了,拥抱本地缓存之王 Caffeine!
- HTML iframe标签下 子页面调用父页面js 容易产生的跨域调用问题 Uncaught DOMException
- 王道训练营3月27日
- 数字信号处理期末总复习
- Java计算卡方值和P值
- 误删除恢复 (extundelete)
- MATLAB多元线性拟合——03
- 双显示器LOL加载游戏提示error无法初始化图形设备解决方法
- jdbc连接oracle11g
- 熔断机制什么意思_熔断机制是什么意思(图文)
- 继电保护matlab程序,自适应微机继电保护的matlab仿真实现 程序与算法
- oracle的权限授予,Oracle赋予用户sysdba权限