zoukankan      html  css  js  c++  java
  • OPENCV下SIFT算法使用方法笔记

    这几天继续在看Lowe大神的SIFT神作,看的眼花手脚抽筋。也是醉了!!!!实在看不下去,来点干货。我们知道opencv下自带SIFT特征检测以及MATCH匹配的库,这些库完全可以让我们进行傻瓜似的操作。但实际用起来的时候还不是那么简单。下文将对一个典型的基于OPENCV的SIFT特征点提取以及匹配的例程进行分析,并由此分析详细的对OPENCV中SIFT算法的使用进行一个介绍。

    OPENCV下SIFT特征点提取与匹配的大致流程如下:

    读取图片-》特征点检测(位置,角度,层)-》特征点描述的提取(16*8维的特征向量)-》匹配-》显示

    其中,特征点提取主要有两个步骤,见上行黄子部分。下面做具体分析。

    1、使用opencv内置的库读取两幅图片

    2、生成一个SiftFeatureDetector的对象,这个对象顾名思义就是SIFT特征的探测器,用它来探测衣服图片中SIFT点的特征,存到一个KeyPoint类型的vector中。这里有必要说keypoint的数据结构,涉及内容较多,具体分析查看opencv中keypoint数据结构分析,里面讲的自认为讲的还算详细(表打我……)。简而言之最重要的一点在于:

    keypoint只是保存了opencv的sift库检测到的特征点的一些基本信息,但sift所提取出来的特征向量其实不是在这个里面,特征向量通过SiftDescriptorExtractor 提取,结果放在一个Mat的数据结构中。这个数据结构才真正保存了该特征点所对应的特征向量。具体见后文对SiftDescriptorExtractor 所生成的对象的详解。

    就因为这点没有理解明白耽误了一上午的时间。哭死!

    3、对图像所有KEYPOINT提取其特征向量:

    得到keypoint只是达到了关键点的位置,方向等信息,并无该特征点的特征向量,要想提取得到特征向量就还要进行SiftDescriptorExtractor 的工作,建立了SiftDescriptorExtractor 对象后,通过该对象,对之前SIFT产生的特征点进行遍历,找到该特征点所对应的128维特征向量。具体方法参见opencv中SiftDescriptorExtractor所做的SIFT特征向量提取工作简单分析。通过这一步后,所有keypoint关键点的特征向量被保存到了一个MAT的数据结构中,作为特征。

    4、对两幅图的特征向量进行匹配,得到匹配值。

    两幅图片的特征向量被提取出来后,我们就可以使用BruteForceMatcher对象对两幅图片的descriptor进行匹配,得到匹配的结果到matches中,这其中具体的匹配方法暂没细看,过段时间补上。

    至此,SIFT从特征点的探测到最后的匹配都已经完成,虽然匹配部分不甚了解,只扫对于如何使用OPENCV进行sift特征的提取有了一定的理解。接下来可以开始进行下一步的工作了。

    附:使用OPENCV下SIFT库做图像匹配的例程

    // opencv_empty_proj.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <opencv2/opencv.hpp>
    #include <opencv2/features2d/features2d.hpp>
    #include<opencv2/nonfree/nonfree.hpp>
    #include<opencv2/legacy/legacy.hpp>
    #include<vector>
    using namespace std;
    using namespace cv;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        const char* imagename = "img.jpg";
    
        //从文件中读入图像
        Mat img = imread(imagename);
        Mat img2=imread("img2.jpg");
    
        //如果读入图像失败
        if(img.empty())
        {
                fprintf(stderr, "Can not load image %s
    ", imagename);
                return -1;
        }
        if(img2.empty())
        {
                fprintf(stderr, "Can not load image %s
    ", imagename);
                return -1;
        }
        //显示图像
        imshow("image before", img);
        imshow("image2 before",img2);
    
    
        //sift特征检测
        SiftFeatureDetector  siftdtc;
        vector<KeyPoint>kp1,kp2;
    
        siftdtc.detect(img,kp1);
        Mat outimg1;
        drawKeypoints(img,kp1,outimg1);
        imshow("image1 keypoints",outimg1);
        KeyPoint kp;
    
        vector<KeyPoint>::iterator itvc;
        for(itvc=kp1.begin();itvc!=kp1.end();itvc++)
        {
            cout<<"angle:"<<itvc->angle<<"	"<<itvc->class_id<<"	"<<itvc->octave<<"	"<<itvc->pt<<"	"<<itvc->response<<endl;
        }
    
        siftdtc.detect(img2,kp2);
        Mat outimg2;
        drawKeypoints(img2,kp2,outimg2);
        imshow("image2 keypoints",outimg2);
    
    
        SiftDescriptorExtractor extractor;
        Mat descriptor1,descriptor2;
        BruteForceMatcher<L2<float>> matcher;
        vector<DMatch> matches;
        Mat img_matches;
        extractor.compute(img,kp1,descriptor1);
        extractor.compute(img2,kp2,descriptor2);
    
    
        imshow("desc",descriptor1);
        cout<<endl<<descriptor1<<endl;
        matcher.match(descriptor1,descriptor2,matches);
    
        drawMatches(img,kp1,img2,kp2,matches,img_matches);
        imshow("matches",img_matches);
    
        //此函数等待按键,按键盘任意键就返回
        waitKey();
        return 0;
    }

    转自http://www.cnblogs.com/cj695/ 作者77695

  • 相关阅读:
    SPAN和DIV的区别
    利用XMLHTTP无刷新添加数据之Post篇
    在Asp.net中上传大文件的解决方法
    在事务中执行批量复制操作
    Microsoft Visual SourceSafe 使用指南
    恢复只有MDF文件的MS SQL数据库
    配置sql server 2000以允许远程访问
    转: Bill Gates 哈佛大学毕业典礼演讲1
    用于对数据库进行操作的类库经验的总结
    用于对数据库进行操作的类库经验的总结 (二)
  • 原文地址:https://www.cnblogs.com/xianyadan/p/6523030.html
Copyright © 2011-2022 走看看