您现在的位置:首页 >> 前端 >> 内容

尺度不变特征变换匹配算法SIFT(2)

时间:2015/11/11 13:28:13 点击:

  核心提示:尺度不变特征变换匹配算法SIFT(2)e-mail:chentravelling@163.comSIFT算法 在10月初,草草学习了一下SIFT(可以戳这里查看),主要是调用opencv函数库了的函数...
尺度不变特征变换匹配算法SIFT(2)
e-mail:chentravelling@163.com
SIFT算法 在10月初,草草学习了一下SIFT(可以戳这里查看),主要是调用opencv函数库了的函数进行了实践,而并没有深入了解SIFT描述子的原理以及opencv中相关函数的用法和参数说明。本篇blog作为LZ的小笔记,记录一下opencv中相关函数的说明,对于SIFT特征的原理后续将花时间继续了解。
C++代码 环境:vs2010+opencv2.3.1+win7 ×64 这部分代码还是使用上一篇SIFT的代码,本篇重在了解一些函数和数据结构。
#include   
#include   
  
using namespace std;  
using namespace cv;  
int main()  
{  
    //read the two input images  
    Mat image1 = imread(image1.jpg);  
    Mat image2 = imread(image2.jpg);  
    //if failed  
    if(image1.empty()||image2.empty())  
    {  
        cout< keypoint1,keypoint2;  
    //detect image with SIFT,get key points  
    siftDetector.detect(image1,keypoint1);  
    Mat outImage1;  
    //draw key points at the out image and show to the user  
    drawKeypoints(image1,keypoint1,outImage1,Scalar(255,0,0));  
  
    imshow(original_image1,image1);  
    imshow(sift_image1,outImage1);  
      
    Mat outImage2;  
      
    siftDetector.detect(image2,keypoint2);  
    drawKeypoints(image2,keypoint2,outImage2,Scalar(255,0,0));  
  
    imshow(sift_image2.jpg,outImage2);  
    //imwrite(sift_result2.jpg,outImage2);  
    //store 10 keypoints in order to watch the effect clearly  
    vector keypoint3,keypoint4;  
    for(int i=0;i<10;i++)  
    {  
        keypoint3.push_back(keypoint1[i]);  
        keypoint4.push_back(keypoint2[i]);  
    }  
    // difine a sift descriptor extractor  
    SiftDescriptorExtractor extractor;  
    //store the descriptor of each image  
    Mat descriptor1,descriptor2;  
    BruteForceMatcher> matcher;  
  
    vector matches;  
    Mat img_matches;  
    //compute the descriptor of each image  
    extractor.compute(image1,keypoint3,descriptor1);  
    extractor.compute(image2,keypoint4,descriptor2);  
    //match  
    matcher.match(descriptor1,descriptor2,matches);  
    //show the result  
    drawMatches(image1,keypoint3,image2,keypoint4,matches,img_matches,Scalar(255,0,0));  
    imshow(matches,img_matches);  
    //store the match_image  
    //imwrite(matches.jpg,img_matches);  
  
    waitKey(0);  
    return 0;  
}  

opencv相关函数和数据结构说明
1.drawMatcher():Draws the found matches of keypoints from two images.
参考:https://docs.opencv.org/2.4/modules/features2d/doc/drawing_function_of_keypoints_and_matches.html C++: void drawMatches(const Mat& img1, const vector& keypoints1, const Mat& img2, const vector& keypoints2, const vector>& matches1to2, Mat& outImg, const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1), const vector>& matchesMask=vector >(), int flags=DrawMatchesFlags::DEFAULT )
 
  • img1 – First source image.
  • keypoints1 – Keypoints from the first source image.
  • img2 – Second source image.
  • keypoints2 – Keypoints from the second source image.
  • matches1to2 – Matches from the first image to the second one, which means that keypoints1[i] has a corresponding point in keypoints2[matches[i]] .
  • outImg – Output image. Its content depends on the flags value defining what is drawn in the output image. See possible flags bit values below.
  • matchColor – Color of matches (lines and connected keypoints). If matchColor==Scalar::all(-1) , the color is generated randomly.
  • singlePointColor – Color of single keypoints (circles), which means that keypoints do not have the matches. If singlePointColor==Scalar::all(-1) , the color is generated randomly.
  • matchesMask – Mask determining which matches are drawn. If the mask is empty, all matches are drawn.
  • flags – Flags setting drawing features. Possible flags bit values are defined by DrawMatchesFlags.
2.DMatch:Class for matching keypoint descriptors: query descriptor index, train descriptor index, train image index, and distance between descriptors. 可参考:https://docs.opencv.org/master/d4/de0/classcv_1_1DMatch.html
       struct DMatch
       {
              //三个构造函数
           DMatch(): queryIdx(-1), trainIdx(-1),imgIdx(-1),distance(std::numeric_limits::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;
       };

一般使用Brute-force descriptor matcher进行匹配,结果并不具有可读性(戳这里看图),那么这里请留意匹配的结果保存在了vector定义的动态数组matches中,这就意味着我们可以对匹配结果进行一系列操作,比如再drawMatches()函数前添加一句:matches.erase(matches.begin()+25,matches.end()); 既可以选择最新的25个匹配结果。


 

作者:网络 来源:生活没有if-els