OpenCV学习之opencv3.X.X实现SURF特征提取的相关改动

众所周知,自opencv3.0版本以来,各种改动层出不穷,与opencv2相比还是有很大差别的。从学习《OpenCV3编程入门》这本书你就能发现,前面可能还好,到后面比较复杂的图像处理,如特征提取,简直大改。3.0把特征提取相关的函数整合在了opencv_contrib中,需要你自己配置,然后就算你花了130分钟配置好了也会发现书中的示例程序照样用不了。因为好多函数包括头文件都有改动,关键作者懒死噜,一丝线索都没透露直接用的opencv2的版本,真素气cry!!!没办法,只能苦了我们这些用opencv3版本的了,最恶熏的是网上还不好找资料,所以花了我130分钟的时间才成功运行呕!接下来就给大家分享吧!

opencv_contrib的配置

首先最重要的一步就是opencv_contrib的配置,需要用到cmake,我用的是VS2015+OpenCV3.2.0,当时配置这个opencv_contrib也是花了不少时间,具体教程我就不介绍了,网上还是挺多的,当然能不能一次成功就看你的运气噜,毕竟不是谁都有神淋眷顾的嘻嘻。下面给出一个配置教程的链接,openCV3.2.0配置VS2013(自用)+opencv_contrib安装,建议大家多找几个教程对比一下,综合起来成功率会高一点。

头文件的变动

我选用的是书上的11.2.3 示例程序:SURF特征提取的代码,代码不长,但是要改的地方真的不少呕。首先是头文件,好多都整合到了opencv_contrib中,像原先放在nonfree.hpp的SURF和legacy.hpp中的BruteForce相关函数,现在都放在了xfeatures2d.hpp里面。所以你只需如下添加这个头文件,当然前提是你要配置好opencv_contrib。

#include<opencv2/xfeatures2d.hpp>
using namespace xfeatures2d;

这个命名空间也非常重要,不然那些相关函数你照样用不了,所以真的很无语呕,麻烦死噜!

定义特征检测类对象

书上的代码是

SurfFeatureDetector detector(minHessian);
detector.detect(srcImage1, keypoint1);

opencv3的版本则改成了如下的指针定义方式,因此需要用箭头调用detect()函数,方法有两种,一种和原来一样用SurfFeatureDetector定义类,另一种方法则是直接用SURF定义,这种似乎是通用法,,包括特征提取也是用这个
方法一:

Ptr< SurfFeatureDetector >detector = SurfFeatureDetector::create(minHessian);
detector->detect(srcImage1, keypoint1);

方法二:

Ptr< SURF> detector =SURF::create(minHessian);
detector->detect(srcImage1, keypoint1);

计算描述符(特征向量)

书上的代码是

SurfDescriptorExtractor extractor;
extractor.compute(srcImage1, keypoint1, descriptors1);

改动如下,由此可得,只要是关于定义类的代码,都可以按照如下的方式进行定义

//方法一
Ptr< SurfDescriptorExtractor> extractor = SurfDescriptorExtractor::create();
//方法二
//Ptr< SURF> extractor = SURF::create();
extractor->compute(srcImage1, keypoint1, descriptors1);

使用BruteForce进行匹配

书上的代码是

BruteForceMatcher< L2< float > > matcher;
matcher.match(descriptors1, descriptors2, matches);

这里与上面有些不同,它照样有两种改动方法,一种与方法一相同,另一种则是直接用头文件提供的BFMatcher定义类,这种与书上类似,不是指针类

//方法一
Ptr< DescriptorMatcher > matcher = DescriptorMatcher::create(“BruteForce”);
matcher->match(descriptors1, descriptors2, matches);
//方法二
//BFMatcher matcher(NORM_L2);
//matcher.match(descriptors1, descriptors2, matches);

完整代码

其它部分就基本一样了,依旧给出完整代码供大家使用,我就是这么大方,比较我很高贵,但是免费嘻嘻!

#include<opencv2/opencv.hpp>
#include<opencv2/xfeatures2d.hpp>
#include<iostream>
using namespace cv;
using namespace xfeatures2d;
using namespace std;

int main()
{
	Mat srcImage1 = imread("linlin.jpg");
	Mat srcImage2 = imread("linlin2.jpg");
	//使用SURF算子检测关键点
	int minHessian = 700; //SURF算法中的Hessian阈值
	Ptr<SurfFeatureDetector>detector = SurfFeatureDetector::create(minHessian);// 定义一个特征检测类对象
	vector<KeyPoint> keypoint1, keypoint2;//vector模板类,存放任意类型的动态数组
	//调用detect函数检测出SURF特征关键点,保存在vector容器中
	detector->detect(srcImage1, keypoint1);
	detector->detect(srcImage2, keypoint2);
	//计算描述符(特征向量)
	//方法一
	Ptr<SurfDescriptorExtractor> extractor = SurfDescriptorExtractor::create();
	//方法二
	//Ptr<SURF> extractor = SURF::create();
	Mat descriptors1, descriptors2;
	extractor->compute(srcImage1, keypoint1, descriptors1);
	extractor->compute(srcImage2, keypoint2, descriptors2);
	//使用BruteForce进行匹配
	//实例化一个匹配器
	//方法一
	Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce");
	//方法二
	//BFMatcher matcher(NORM_L2);
	vector<DMatch> matches;
	//匹配两幅图中的描述子
	matcher->match(descriptors1, descriptors2, matches);
	//绘制从两个图像中匹配出的关键点
	Mat imgMatches;
	drawMatches(srcImage1, keypoint1, srcImage2, keypoint2, matches, imgMatches); //进行绘制

	imshow("匹配图", imgMatches);
	waitKey(0);
	return 0;
}

实验效果

依旧选用宇宙天后的婊情,但是天后婊情太过丰富,所以匹配效果嘛,我和某蔡姓女士婊示清者自清靴靴!(注意两张图片最好调成尺寸大小相同呦)
在这里插入图片描述

发布了17 篇原创文章 · 获赞 3 · 访问量 1809

猜你喜欢

转载自blog.csdn.net/weixin_43350361/article/details/88887304