【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
来源:互联网 发布:linux ln s 什么意思 编辑:程序博客网 时间:2024/06/05 22:35
本系列文章由@浅墨_毛星云 出品,转载请注明出处。
文章链接: http://blog.csdn.net/poem_qianmo/article/details/30974513
作者:毛星云(浅墨) 微博:http://weibo.com/u/1723155442
知乎:http://www.zhihu.com/people/mao-xing-yun
邮箱: happylifemxy@163.com
写作当前博文时配套使用的OpenCV版本:2.4.9本篇文章中,我们一起探讨了OpenCV中重映射和SURF特征点检测相关的知识点,主要一起了解OpenCV中重映射相关的函数remap,SURF算法在OpenCV中的体现与应用。此博文一共有三个配套的麻雀虽小但五脏俱全的示例程序,其经过浅墨详细注释过的代码都在文中贴出,且文章最后提供了综合示例程序的下载。
依然是先看看程序运行截图。
重映射:
SURF特征点检测:
一、OpenCV重映射
1.1 重映射的概念简析
重映射,就是把一幅图像中某位置的像素放置到另一个图片指定位置的过程。为了完成映射过程, 我们需要获得一些插值为非整数像素的坐标,因为源图像与目标图像的像素坐标不是一一对应的。一般情况下,我们通过重映射来表达每个像素的位置 (x,y),像这样 :
g(x,y) = f ( h(x,y) )
在这里, g( ) 是目标图像, f() 是源图像, 而h(x,y) 是作用于 (x,y) 的映射方法函数。
来看个例子。 若有一幅图像 I ,想满足下面的条件作重映射:
h(x,y) = (I.cols - x, y )
这样的话,图像会按照 x 轴方向发生翻转。那么,源图像和效果图分别如下:
在OpenCV中,我们用函数remap( )来实现简单重映射,下面我们就一起来看看这个函数。
1.2 remap( )函数解析
remap( )函数会根据我们指定的映射形式,将源图像进行重映射几何变换,基于的式子如下:
需要注意,此函数不支持就地(in-place)操作。看看其原型和参数。
- 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位或者浮点型图像。
- 第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放函数调用后的输出结果,需和源图片有一样的尺寸和类型。
- 第三个参数,InputArray类型的map1,它有两种可能的表示对象。
- 表示点(x,y)的第一个映射。
- 表示CV_16SC2 , CV_32FC1 或CV_32FC2类型的X值。
- 第四个参数,InputArray类型的map2,同样,它也有两种可能的表示对象,而且他是根据map1来确定表示那种对象。
- 若map1表示点(x,y)时。这个参数不代表任何值。
- 表示CV_16UC1 , CV_32FC1类型的Y值(第二个值)。
- 第五个参数,int类型的interpolation,插值方式,之前的resize( )函数中有讲到,需要注意,resize( )函数中提到的INTER_AREA插值方式在这里是不支持的,所以可选的插值方式如下:
- INTER_NEAREST - 最近邻插值
- INTER_LINEAR – 双线性插值(默认值)
- INTER_CUBIC – 双三次样条插值(逾4×4像素邻域内的双三次插值)
- INTER_LANCZOS4 -Lanczos插值(逾8×8像素邻域的Lanczos插值)
- 第六个参数,int类型的borderMode,边界模式,有默认值BORDER_CONSTANT,表示目标图像中“离群点(outliers)”的像素值不会被此函数修改。
- 第七个参数,const Scalar&类型的borderValue,当有常数边界时使用的值,其有默认值Scalar( ),即默认值为0。
1.3 详细注释的重映射示例程序
下面放出精简后的以remap函数为核心的示例程序,方便大家快速掌握remap函数的使用方法。
显示效果图:
最近世界杯正如火如荼地进行着,这里的图片素材就是巴西队的球星们~
1.4 OpenCV2.X中remap函数源代码
这里我们放出remap函数的源码,供需要了解其实现细节的朋友们观看,浅墨在这里不花时间对其进行剖析。
好了,重映射先就讲这么多,在文章末尾还有一个综合一点的示例程序供大家学习。下面我们开始讲解SURF相关的内容。
二.SURF特征点检测
SURF算法有一些不错的内容和用法,OpenCV中使用颇多,浅墨会花一些篇幅对其进行讲解。今天的这篇文章只是一个小小的开头,主要介绍SURF特征点检测。
先简单了解一下SURF算法的大概内容吧。
2.1 SURF算法概览
SURF,我们简单介绍一下,英语全称为SpeededUp Robust Features,直译的话就是“加速版的具有鲁棒性的特征“算法,由Bay在2006年首次提出。SURF是尺度不变特征变换算法(SIFT算法)的加速版。一般来说,标准的SURF算子比SIFT算子快好几倍,并且在多幅图片下具有更好的稳定性。SURF最大的特征在于采用了harr特征以及积分图像的概念,这大大加快了程序的运行时间。SURF可以应用于计算机视觉的物体识别以及3D重构中。
PS: 由于我们的专栏侧重点是教大家如何快速入门OpenCV编程,不是来进行图像处理科普的,所以原理部分不会花笔墨多讲。一方面是浅墨也不喜欢讲这些枯燥的概念,另一方面是大家肯定应该也不喜欢看这些枯燥的原理,大家是喜欢看代码的〜( ̄▽ ̄〜)。就像小魏CPU童鞋在博客上写的,“Talk is cheap. Show me thecode.”
所以原理部分大家就自行用搜索引擎去学习吧,浅墨会将更多的笔墨用来分享网络上独一无二的干货。
2.2 前世今生——SURF类相关OpenCV源码剖析
OpenCV中关于SURF算法的部分,常常涉及到的是SURF、SurfFeatureDetector、SurfDescriptorExtractor这三个类,这一小节我们就来对他们进行人肉,挖挖其背景,看看他们究竟是什么来头。
在D:\Program Files (x86)\opencv\sources\modules\nonfree\include\opencv2\nonfree下的features2d.hpp头文件中,我们可以发现这样两句定义:
我们都知道,typedef声明是为现有类型创建一个新的名字,类型别名。这就表示,SURF类忽然同时有了两个新名字SurfFeatureDetector以及SurfDescriptorExtractor。
也就是说,我们平常使用的SurfFeatureDetector类和SurfDescriptorExtractor类,其实就是SURF类,他们三者等价。
然后在这两句定义的上方,我们可以看到SURF类的类声明全貌:
可以观察到,SURF类公共继承自Feature2D类,我们再次进行转到,可以在路径d:\Program Files(x86)\opencv\build\include\opencv2\features2d\features2d.hpp看到Feature2D类的声明:
显然,Feature2D类又是公共继承自FeatureDetector以及 DescriptorExtractor类。继续刨根问底,我们看看其父类FeatureDetector以及 DescriptorExtractor类的定义。
首先是FeatureDetector类:
这里,我们看到了我们以后经常会用到的detect( )方法重载的两个原型,原来是SURF类经过两层的继承,从FeatureDetector类继承而来的。
同样,看看SURF类的另一个“爷爷”DescriptorExtractor类的声明。
上述代码表明FeatureDetector 类和DescriptorExtractor类都虚继承自Algorithm基类。
呼,历经千辛万苦,终于,我们找到SURF类德高望重的祖先——OpenCV中的Algorithm基类。看看其原型声明:
关于这几个类缠绵悱恻的关系,画个图就一目了然了,也就是这样的过程:
3.3 drawKeypoints函数详解
因为接下来的示例程序需要用到drawKeypoints函数,我们在这里顺便讲一讲。
顾名思义,此函数用于绘制关键点。
- 第一个参数,const Mat&类型的src,输入图像。
- 第二个参数,const vector<KeyPoint>&类型的keypoints,根据源图像得到的特征点,它是一个输出参数。
- 第三个参数,Mat&类型的outImage,输出图像,其内容取决于第五个参数标识符falgs。
- 第四个参数,const Scalar&类型的color,关键点的颜色,有默认值Scalar::all(-1)。
- 第五个参数,int类型的flags,绘制关键点的特征标识符,有默认值DrawMatchesFlags::DEFAULT。可以在如下这个结构体中选取值。
- 第一个参数,const Mat&类型的src,输入图像。
- 第二个参数,const vector<KeyPoint>&类型的keypoints,根据源图像得到的特征点,它是一个输出参数。
- 第三个参数,Mat&类型的outImage,输出图像,其内容取决于第五个参数标识符falgs。
- 第四个参数,const Scalar&类型的color,关键点的颜色,有默认值Scalar::all(-1)。
- 第五个参数,int类型的flags,绘制关键点的特征标识符,有默认值DrawMatchesFlags::DEFAULT。可以在如下这个结构体中选取值。
三、综合示例部分
因为这次的两个知识点关联度不大,所以不方便组织起来成为一个综合示例程序。在这里我们分开将其放出。
3.1 重映射综合示例程序
先放出以remap为核心的综合示例程序,可以用按键控制四种不同的映射模式。且利用了OpenCV版本标识宏“CV_VERSION”,在帮助文字相关代码中加入了一句:
便可以智能检测出当前使用的OpenCV版本,并输出。如图:
按键说明也可以由上图看出。
放出这个程序详细注释的源代码:
运行效果图。首先是原始图:
第一种重映射:
第二种重映射:
第三种重映射:
第四种重映射:
3.2 SURF特征点检测综合示例程序
这个示例程涉及到如下三个方面:
- 使用 FeatureDetector 接口来发现感兴趣点。
- 使用 SurfFeatureDetector 以及其函数 detect 来实现检测过程
- 使用函数 drawKeypoints 绘制检测到的关键点。
- 使用 FeatureDetector 接口来发现感兴趣点。
- 使用 SurfFeatureDetector 以及其函数 detect 来实现检测过程
- 使用函数 drawKeypoints 绘制检测到的关键点。
详细注释的源代码:
这里的图片素材是浅墨自己用手机拍的自己写的书:)
第一组图片对比效果:
第二组图片对比效果:
本篇文章的配套源代码请点击这里下载:
【浅墨OpenCV入门教程之十七】配套源代码之【重映射】 下载
------------------------------------------------------------------------
【浅墨OpenCV入门教程之十七】配套源代码之【SURF特征点检测】下载
- 【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
- 【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
- 【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
- 【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
- 【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
- 【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
- 【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
- 【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
- 【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
- [转] 【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
- 【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
- OpenCV之十七 OpenCV重映射 & SURF特征点检测合辑
- OpenCV 重映射 & SURF特征点检测合辑
- opencv重映射&surf特征点检测
- 【OpenCV入门教程之十八】OpenCV仿射变换 & SURF特征点描述合辑
- 【OpenCV入门教程之十八】OpenCV仿射变换 & SURF特征点描述合辑
- 【OpenCV入门教程之十八】OpenCV仿射变换 & SURF特征点描述合辑
- 【OpenCV入门教程之十八】OpenCV仿射变换 & SURF特征点描述合辑
- rename命令和批量重命名
- 为了远方的爱:2016年逐浪软件-东方红公益基金捐赠致辞
- This Android SDK requires Android Developer Toolkit version 20.0.0 or above
- 求只出现一次的两个整数
- spring整合activemq发送消息[queue类型]实例
- 【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
- Android开发之语音合成及听写(二)
- Hibernate关联关系配置(一对多、一对一和多对多)
- Android设计模式 单例模式
- 局域网
- 9个完整android开源app项目
- 数据结构笔记之图(一)
- 【OpenCV入门教程之十八】OpenCV仿射变换 & SURF特征点描述合辑
- Spring基于事件驱动模型的订阅发布模式代码实例详解