OpenCV2.4.4中调用SIFT特征检测器进行图像匹配

来源:互联网 发布:java 查询条件封装 编辑:程序博客网 时间:2024/05/29 07:49

OpenCV中一些相关结构说明:

特征点类:

查看文本打印?
  1. class KeyPoint  
  2. {  
  3.        Point2f  pt;  //坐标  
  4.        float  size; //<strong>特征</strong>点邻域直径  
  5.        float  angle; //<strong>特征</strong>点的方向,值为[0,360),负值表示不使用  
  6.        float  response; //  
  7.        int  octave; //<strong>特征</strong>点所在的<strong>图像</strong>金字塔的组  
  8.        int  class_id; //用于聚类的id  
  9. }  

存放匹配结果的结构:

查看文本打印?
  1. struct DMatch  
  2. {  
  3.        //三个构造函数  
  4.     DMatch(): queryIdx(-1), trainIdx(-1),imgIdx(-1),distance(std::numeric_limits<float>::max()) {}  
  5.     DMatch(int  _queryIdx, int  _trainIdx, float  _distance ) :  
  6.                      queryIdx( _queryIdx),trainIdx( _trainIdx), imgIdx(-1),distance( _distance) {}  
  7.     DMatch(int  _queryIdx, int  _trainIdx, int  _imgIdx, float  _distance ) :  
  8.             queryIdx(_queryIdx), trainIdx( _trainIdx), imgIdx( _imgIdx),distance( _distance) {}  
  9.   
  10.     intqueryIdx;  //此<strong>匹配</strong>对应的查询<strong>图像</strong>的<strong>特征</strong>描述子索引  
  11.     inttrainIdx;   //此<strong>匹配</strong>对应的训练(模板)<strong>图像</strong>的<strong>特征</strong>描述子索引  
  12.     intimgIdx;    //训练<strong>图像</strong>的索引(若有多个)  
  13.     float distance;  //两个<strong>特征</strong>向量之间的欧氏距离,越小表明<strong>匹配</strong>度越高。  
  14.     booloperator < (const DMatch &m) const;  
  15. };  

       说明:以两个特征点描述子(特征向量)之间的欧氏距离作为特征匹配的相似度准则,假设特征点对p和q的

               特征描述子分别为Desp和Desq,则其欧氏距离定义为:


                所以每个匹配分别对应训练图像(train)和查询图像(query)中的一个特征描述子(特征向量)。



查看文本打印?
  1. #include "opencv2/highgui/highgui.hpp"  
  2. #include "opencv2/imgproc/imgproc.hpp"  
  3. #include "opencv2/nonfree/nonfree.hpp"  
  4. #include "opencv2/nonfree/features2d.hpp"  
  5. #include <iostream>  
  6. #include <stdio.h>  
  7. #include <stdlib.h>  
  8.   
  9. using namespace cv;  
  10. using namespace std;  
  11.   
  12. int main()  
  13. {  
  14.     initModule_nonfree();//初始化模块,使用SIFT或SURF时用到  
  15.     Ptr<FeatureDetector> detector = FeatureDetector::create( "SIFT" );//创建SIFT<strong>特征</strong><strong>检测器</strong>  
  16.     Ptr<DescriptorExtractor> descriptor_extractor = DescriptorExtractor::create( "SIFT" );//创建<strong>特征</strong>向量生成器  
  17.     Ptr<DescriptorMatcher> descriptor_matcher = DescriptorMatcher::create( "BruteForce" );//创建<strong>特征</strong><strong>匹配</strong>器  
  18.     if( detector.empty() || descriptor_extractor.empty() )  
  19.         cout<<"fail to create detector!";  
  20.   
  21.     //读入<strong>图像</strong>  
  22.     Mat img1 = imread("desk.jpg");  
  23.     Mat img2 = imread("desk_glue.jpg");  
  24.   
  25.     //<strong>特征</strong>点检测  
  26.     double t = getTickCount();//当前滴答数  
  27.     vector<KeyPoint> keypoints1,keypoints2;  
  28.     detector->detect( img1, keypoints1 );//检测img1中的SIFT<strong>特征</strong>点,存储到keypoints1中  
  29.     detector->detect( img2, keypoints2 );  
  30.     cout<<"<strong>图像</strong>1<strong>特征</strong>点个数:"<<keypoints1.size()<<endl;  
  31.     cout<<"<strong>图像</strong>2<strong>特征</strong>点个数:"<<keypoints2.size()<<endl;  
  32.   
  33.     //根据<strong>特征</strong>点计算<strong>特征</strong>描述子矩阵,即<strong>特征</strong>向量矩阵  
  34.     Mat descriptors1,descriptors2;  
  35.     descriptor_extractor->compute( img1, keypoints1, descriptors1 );  
  36.     descriptor_extractor->compute( img2, keypoints2, descriptors2 );  
  37.     t = ((double)getTickCount() - t)/getTickFrequency();  
  38.     cout<<"SIFT算法用时:"<<t<<"秒"<<endl;  
  39.   
  40.   
  41.     cout<<"<strong>图像</strong>1<strong>特征</strong>描述矩阵大小:"<<descriptors1.size()  
  42.         <<",<strong>特征</strong>向量个数:"<<descriptors1.rows<<",维数:"<<descriptors1.cols<<endl;  
  43.     cout<<"<strong>图像</strong>2<strong>特征</strong>描述矩阵大小:"<<descriptors2.size()  
  44.         <<",<strong>特征</strong>向量个数:"<<descriptors2.rows<<",维数:"<<descriptors2.cols<<endl;  
  45.   
  46.     //画出<strong>特征</strong>点  
  47.     Mat img_keypoints1,img_keypoints2;  
  48.     drawKeypoints(img1,keypoints1,img_keypoints1,Scalar::all(-1),0);  
  49.     drawKeypoints(img2,keypoints2,img_keypoints2,Scalar::all(-1),0);  
  50.     //imshow("Src1",img_keypoints1);  
  51.     //imshow("Src2",img_keypoints2);  
  52.   
  53.     //<strong>特征</strong><strong>匹配</strong>  
  54.     vector<DMatch> matches;//<strong>匹配</strong>结果  
  55.     descriptor_matcher->match( descriptors1, descriptors2, matches );//<strong>匹配</strong>两个<strong>图像</strong>的<strong>特征</strong>矩阵  
  56.     cout<<"Match个数:"<<matches.size()<<endl;  
  57.   
  58.     //计算<strong>匹配</strong>结果中距离的最大和最小值  
  59.     //距离是指两个<strong>特征</strong>向量间的欧式距离,表明两个<strong>特征</strong>的差异,值越小表明两个<strong>特征</strong>点越接近  
  60.     double max_dist = 0;  
  61.     double min_dist = 100;  
  62.     for(int i=0; i<matches.size(); i++)  
  63.     {  
  64.         double dist = matches[i].distance;  
  65.         if(dist < min_dist) min_dist = dist;  
  66.         if(dist > max_dist) max_dist = dist;  
  67.     }  
  68.     cout<<"最大距离:"<<max_dist<<endl;  
  69.     cout<<"最小距离:"<<min_dist<<endl;  
  70.   
  71.     //筛选出较好的<strong>匹配</strong>点  
  72.     vector<DMatch> goodMatches;  
  73.     for(int i=0; i<matches.size(); i++)  
  74.     {  
  75.         if(matches[i].distance < 0.31 * max_dist)  
  76.         {  
  77.             goodMatches.push_back(matches[i]);  
  78.         }  
  79.     }  
  80.     cout<<"goodMatch个数:"<<goodMatches.size()<<endl;  
  81.   
  82.     //画出<strong>匹配</strong>结果  
  83.     Mat img_matches;  
  84.     //红色连接的是<strong>匹配</strong>的<strong>特征</strong>点对,绿色是未<strong>匹配</strong>的<strong>特征</strong>点  
  85.     drawMatches(img1,keypoints1,img2,keypoints2,goodMatches,img_matches,  
  86.                 Scalar::all(-1)/*CV_RGB(255,0,0)*/,CV_RGB(0,255,0),Mat(),2);  
  87.   
  88.     imshow("MatchSIFT",img_matches);  
  89.     waitKey(0);  
  90.     return 0;  
  91. }  
0 0