您的位置:首页 > 运维架构

OpenCV学习之旅9——特征检测与匹配(2)

2018-02-20 20:08 387 查看

1. SURF特征提取

在OpenCV中,使用SURF进行特征点描述主要是使用drawMatches 方法和BruteForceMatcher类。

1.1 drawMatches()函数

drawMatches用于绘制出相匹配的两个图像的关键点,该函数有两个函数原型。

void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
const Mat& img2,
const vector<KeyPoint>& keypoints2,
const vector<DMatch>& matches1to2,
Mat& outImg,
const Scalar& singlePointColor=Scalar::all(-1),
int flags=DrawMatchesFlags::DEFAULT );

void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
const Mat& img2, const vector<KeyPoint>& keypoints2,
Mat& outImg,
const Scalar& matchColor=Scalar::all(-1),
const Scalar& singlePointColor=Scalar::all(-1),
const vector<vector<char> >& matchesMask=vector<vector<char> >(),
int flags=DrawMatchesFlags::DEFAULT );


第一个参数:第一幅源图像;

第二个参数:第一幅图像的特征点,为输出参数;

第三个参数:第二幅源图像;

第四个参数:第二幅图像的特征点,为输出参数;

第五个参数:matches1to2,第一幅图像到第二幅图像的匹配点;

第六个参数:输出图像;

第七个参数:线和关键点的颜色,默认Scalar::all(-1)表随机颜色;

第八个参数:单一特征点的颜色,默认值表随机颜色;

第九个参数:确定哪些匹配是要绘制出来的掩码,默认值表所有的都要绘制;

第十个参数:特征绘制的标识符。

1.2 BruteForceMatches类

template<class Distance>
class CV_EXPORTS BruteForceMatcher : public BFMatcher
{
public:
BruteForceMatcher( Distance d = Distance() ) : BFMatcher(Distance::normType, false) {(void)d;}
virtual ~BruteForceMatcher() {}
};


1.3 程序实例

#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <opencv2/nonfree/nonfree.hpp>
#include<opencv2/legacy/legacy.hpp>
#include <iostream>
using namespace cv;
using namespace std;

//-----------------------------------【main( )函数】--------------------------------------------
//      描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main(  )
{
//【0】改变console字体颜色
system("color 1F");

//【1】载入素材图
Mat srcImage1 = imread("1.jpg",1);
Mat srcImage2 = imread("2.jpg",1);
if( !srcImage1.data || !srcImage2.data )
{ printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; }

//【2】使用SURF算子检测关键点
int minHessian = 700;//SURF算法中的hessian阈值
SurfFeatureDetector detector( minHessian );//定义一个SurfFeatureDetector(SURF) 特征检测类对象
std::vector<KeyPoint> keyPoint1, keyPoints2;//vector模板类,存放任意类型的动态数组

//【3】调用detect函数检测出SURF特征关键点,保存在vector容器中
detector.detect( srcImage1, keyPoint1 );
detector.detect( srcImage2, keyPoints2 );

//【4】计算描述符(特征向量)
SurfDescriptorExtractor extractor;
Mat descriptors1, descriptors2;
extractor.compute( srcImage1, keyPoint1, descriptors1 );
extractor.compute( srcImage2, keyPoints2, descriptors2 );

//【5】使用BruteForce进行匹配
// 实例化一个匹配器
BruteForceMatcher< L2<float> > matcher;
std::vector< DMatch > matches;
//匹配两幅图中的描述子(descriptors)
matcher.match( descriptors1, descriptors2, matches );

//【6】绘制从两个图像中匹配出的关键点
Mat imgMatches;
drawMatches( srcImage1, keyPoint1, srcImage2, keyPoints2, matches, imgMatches );//进行绘制

//【7】显示效果图
imshow("匹配图", imgMatches );

waitKey(0);
return 0;
}


2.使用FLANN进行特征点匹配

FLANN——快速最近邻逼近搜索函数库,Fast Libray for Approximate Nearest Neighbors。

2.1 FlannBasedMatcher类

class CV_EXPORTS_W FlannBasedMatcher : public DescriptorMatcher
{
//
}


2.2 找到最佳匹配:DescriptorMatcher::match方法

2.3 程序实例

#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <opencv2/nonfree/nonfree.hpp>
#include<opencv2/legacy/legacy.hpp>
#include <iostream>
using namespace cv;
using namespace std;

//-----------------------------------【main( )函数】--------------------------------------------
//   描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main( int argc, char** argv )
{
//【0】改变console字体颜色
system("color 4F");

//【1】载入源图片
Mat img_1 = imread("1.jpg", 1 );
Mat img_2 = imread( "2.jpg", 1 );
if( !img_1.data || !img_2.data ) { printf("读取图片image0错误~! \n"); return false; }

//【2】利用SURF检测器检测的关键点
int minHessian = 300;
SURF detector( minHessian );
std::vector<KeyPoint> keypoints_1, keypoints_2;
detector.detect( img_1, keypoints_1 );
detector.detect( img_2, keypoints_2 );

//【3】计算描述符(特征向量)
SURF extractor;
Mat descriptors_1, descriptors_2;
extractor.compute( img_1, keypoints_1, descriptors_1 );
extractor.compute( img_2, keypoints_2, descriptors_2 );

//【4】采用FLANN算法匹配描述符向量
FlannBasedMatcher matcher;
std::vector< DMatch > matches;
matcher.match( descriptors_1, descriptors_2, matches );
double max_dist = 0; double min_dist = 100;

//【5】快速计算关键点之间的最大和最小距离
for( int i = 0; i < descriptors_1.rows; i++ )
{
double dist = matches[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}
//输出距离信息
printf("> 最大距离(Max dist) : %f \n", max_dist );
printf("> 最小距离(Min dist) : %f \n", min_dist );

//【6】存下符合条件的匹配结果(即其距离小于2* min_dist的),使用radiusMatch同样可行
std::vector< DMatch > good_matches;
for( int i = 0; i < descriptors_1.rows; i++ )
{
if( matches[i].distance < 2*min_dist )
{ good_matches.push_back( matches[i]); }
}

//【7】绘制出符合条件的匹配点
Mat img_matches;
drawMatches( img_1, keypoints_1, img_2, keypoints_2,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

//【8】输出相关匹配点信息
for( int i = 0; i < good_matches.size(); i++ )
{ printf( ">符合条件的匹配点 [%d] 特征点1: %d  -- 特征点2: %d  \n", i, good_matches[i].queryIdx, good_matches[i].trainIdx ); }

//【9】显示效果图
imshow( "匹配效果图", img_matches );

//按任意键退出程序
waitKey(0);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: