opencv2.4 sift算法的使用

来源:互联网 发布:常用国家域名 编辑:程序博客网 时间:2024/06/05 15:09

与opencv2.3.1版本的sift算法的编程方法有所不同,貌似opencv2.4版本之后将sift、surf算法移到了nonfree区。

所以,需要包换的头文件:

#include <nonfree/features2d.hpp>

#include <nonfree/nonfree.hpp>

增加静态链接库:

opencv_nonfree249d.lib和opencv_features2d249d.lib

注:在使用 initModule_nonfree()函数时,需要用到 opencv_nonfree249d.lib 这个链接库,才能不出现“无法解析的外部符号”。


具体SIFT算法的运算过程是这样的:

1、用FeatureDetector创建相应的特征检测器,并调用FeatureDetector::detect()函数,来求取特征点,并保存在KeyPoint的vector容器中。

特征检测器如下:

Ptr<FeatureDetector> detector = FeatureDetector::create( "SIFT" );//创建SIFT特征检测器 

其中FeatureDetector::create()函数的参数可选:

• "FAST" – FastFeatureDetector

• "STAR" – StarFeatureDetector
• "SIFT" – SIFT (nonfree module)
• "SURF" – SURF (nonfree module)
• "ORB" – ORB
• "BRISK" – BRISK
• "MSER" – MSER
• "GFTT" – GoodFeaturesToTrackDetector
• "HARRIS" – GoodFeaturesToTrackDetector with Harris detector enabled
• "Dense" – DenseFeatureDetector
• "SimpleBlob" – SimpleBlobDetector


Keypoints特征点类定义如下:

       class KeyPoint       {              Point2f  pt;  //坐标              float  size; //特征点邻域直径              float  angle; //特征点的方向,值为[0,360),负值表示不使用              float  response; //              int  octave; //特征点所在的图像金字塔的组              int  class_id; //用于聚类的id       }


2、用DescriptorExtractor创建相应的特征向量生成器,并调用DescriptorExtractor::compute()函数,来求取特征矩阵,保存在Mat型变量中。

特征向量生成器定义如下:

Ptr<DescriptorExtractor> descriptor_extractor = DescriptorExtractor::create( "SIFT" );//创建特征向量生成器  

其中DescriptorExtractor::create()函数的参数如下:

• "SIFT" – SIFT
• "SURF" – SURF
• "BRIEF" – BriefDescriptorExtractor
• "BRISK" – BRISK
• "ORB" – ORB
• "FREAK" – FREAK


3、用DescriptorMatcher创建特征匹配器,并调用DescriptorMatcher::match()函数,求取两幅图像之间的匹配点,并保存在DMatch的vector容器中。

特征匹配器定义如下:

Ptr<DescriptorMatcher> descriptor_matcher = DescriptorMatcher::create( "BruteForce" );//创建特征匹配器
其中DescriptorMatcher::create()函数的参数如下,对应不同的匹配算法:

– BruteForce (it uses L2 ) 
– BruteForce-L1
– BruteForce-Hamming
– BruteForce-Hamming(2)
– FlannBased


DMatch结构体定义如下:

       struct DMatch       {              //三个构造函数           DMatch(): queryIdx(-1), trainIdx(-1),imgIdx(-1),distance(std::numeric_limits<float>::max()) {}           DMatch(int  _queryIdx, int  _trainIdx, float  _distance ) :                            queryIdx( _queryIdx),trainIdx( _trainIdx), imgIdx(-1),distance( _distance) {}           DMatch(int  _queryIdx, int  _trainIdx, int  _imgIdx, float  _distance ) :                   queryIdx(_queryIdx), trainIdx( _trainIdx), imgIdx( _imgIdx),distance( _distance) {}            intqueryIdx;  //此匹配对应的查询图像的特征描述子索引           inttrainIdx;   //此匹配对应的训练(模板)图像的特征描述子索引           intimgIdx;    //训练图像的索引(若有多个)           float distance;  //两个特征向量之间的欧氏距离,越小表明匹配度越高。           booloperator < (const DMatch &m) const;       };


4、调用drawMatches()函数绘制匹配结果。


例程如下:

#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <features2d/features2d.hpp>#include <nonfree/features2d.hpp>#include <nonfree/nonfree.hpp>#include <iostream>using namespace cv;using namespace std;int main(){/*SIFT算法*/Mat image1=imread("E:\\test\\lena.bmp",0);Mat image2=imread("E:\\test\\lena_Match.bmp",0);initModule_nonfree();   //初始化模块,使用SIFT或SURF时用到  Ptr<FeatureDetector> detector = FeatureDetector::create( "SIFT" );//创建SIFT特征检测器  Ptr<DescriptorExtractor> descriptor_extractor = DescriptorExtractor::create( "SIFT" );//创建特征向量生成器  Ptr<DescriptorMatcher> descriptor_matcher = DescriptorMatcher::create( "BruteForce" );//创建特征匹配器  if( detector.empty() || descriptor_extractor.empty() )  cout<<"fail to create detector!"; //检测特征点vector<KeyPoint> vkKeypoints1,vkKeypoints2;detector->detect(image1,vkKeypoints1);detector->detect(image2,vkKeypoints2);cout<<"图像1特征点个数:"<<vkKeypoints1.size()<<endl;cout<<"图像2特征点个数:"<<vkKeypoints2.size()<<endl;//根据特征点计算特征描述子矩阵,即特征向量矩阵 Mat mDescriptors1,mDescriptors2;descriptor_extractor->compute( image1, vkKeypoints1, mDescriptors1);descriptor_extractor->compute(image2, vkKeypoints2, mDescriptors2);cout<<"图像1特征描述矩阵大小:"<<mDescriptors1.size() <<",特征向量个数:"<<mDescriptors1.rows<<",维数:"<<mDescriptors1.cols<<endl;cout<<"图像2特征描述矩阵大小:"<<mDescriptors2.size() <<",特征向量个数:"<<mDescriptors2.rows<<",维数:"<<mDescriptors2.cols<<endl;//特征匹配vector<DMatch> vdMatches;descriptor_matcher->match(mDescriptors1,mDescriptors2,vdMatches);//筛选匹配结果//距离是指两个特征向量间的欧式距离,表明两个特征的差异,值越小表明两个特征点越接近int nMinDis=100,nMaxDis=0;for (int i=0;i<vdMatches.size();i++){if (nMinDis>vdMatches[i].distance)nMinDis=vdMatches[i].distance;if (nMaxDis<vdMatches[i].distance)nMaxDis=vdMatches[i].distance;}cout<<"最大距离:"<<nMaxDis<<endl;  cout<<"最小距离:"<<nMinDis<<endl; vector<DMatch> vdGoodMatches;for (int i=0;i<vdMatches.size();i++){if (vdMatches[i].distance < nMaxDis * 0.3)//0.3为参考值,距离是指两个特征向量间的欧式距离,表明两个特征的差异,//值越小表明两个特征点越接近 。越小结果越精,但剩下的点少;越大结果//越粗,剩下的点多vdGoodMatches.push_back(vdMatches[i]);}//画出匹配结果Mat mMatchResult;drawMatches(image1,vkKeypoints1,image2,vkKeypoints2,vdGoodMatches,mMatchResult,Scalar::all(-1),//Scalar::all(-1)表示将各匹配点颜色随机生成CV_RGB(0,255,0),//未匹配点的颜色Mat(),DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);//NOT_DRAW_SINGLE_POINTS 不画出未匹配点namedWindow("Match");imshow("Match",mMatchResult);waitKey();return 0;}



注:如果仅仅想画出特征点,可调用drawKeypoints()函数实现,如:drawKeypoints(img1,keypoints1,img_keypoints1,Scalar::all(-1),0); 

运行结果:




参考:http://blog.csdn.net/masibuaa/article/details/8998601


0 0
原创粉丝点击