3. opencv提取SIFT特征

作者: 在河之简 | 来源:发表于2015-05-12 13:16 被阅读5544次

    opencv中sift特征提取的步骤

    1. 使用SiftFeatureDetector 的detect方法检测特征存入一个向量里,并使用drawKeypoints在图中标识出来
    2. SiftDescriptorExtractor 的compute方法提取特征描述符,特征描述符是一个矩阵
    3. 使用匹配器matcher对描述符进行匹配,匹配结果保存由DMatch的组成的向量里
    4. 设置距离阈值,使得匹配的向量距离小于最小距离的2被才能进入最终的结果,用DrawMatch可以显示

    代码

    
    // 使用Flann进行特征点匹配.cpp : 定义控制台应用程序的入口点。
    
    //
    
    #include "stdafx.h"
    
    #include <opencv2/opencv.hpp>
    
    #include <highgui/highgui.hpp>
    
    #include <features2d/features2d.hpp>
    
    #include <nonfree/nonfree.hpp>
    
    #include <vector>
    
    using namespace cv;
    
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    
    {
    
        Mat input1 = imread("E://code//test//image//box.png", 1);
    
        Mat input2 = imread("E://code//test//image//box_in_scene.jpg", 1);
    
        if (input1.empty()||input2.empty())
    
        {
    
            cout << "不能正常加载图片" << endl;
    
            system("pause");
    
            return -1;
    
        }
    
        /************************************************************************/
    
        /*下面进行提取特征点*/
    
        /************************************************************************/
    
        SiftFeatureDetector feature;
    
        vector<KeyPoint> kerpoints1;
    
        feature.detect(input1, kerpoints1);
    
        Mat output1;
    
        drawKeypoints(input1, kerpoints1, output1);
    
        vector<KeyPoint> kerpoints2;
    
        feature.detect(input2, kerpoints2);
    
        Mat output2;
    
        drawKeypoints(input2, kerpoints2, output2);
    
        imshow("提取特征点后的box.png", output1);
    
        imshow("提取特征点后的box_in_scene.png", output2);
    
        imwrite("提取特征点后的box.png", output1);
    
        imwrite("提取特征点后的box_in_scene.png", output2);
    
        cout << "box提取的特征点数为:" << kerpoints1.size() << endl;
    
        cout << "box_in_scene的特征点数为:" << kerpoints2.size() << endl;
    
        /************************************************************************/
    
        /* 下面进行特征向量提取 */
    
        /************************************************************************/
    
        SiftDescriptorExtractor descript;
    
        Mat description1;
    
        descript.compute(input1, kerpoints1, description1);
    
        Mat description2;
    
        descript.compute(input2, kerpoints2, description2);
    
        /************************************************************************/
    
        /* 下面进行特征向量临近匹配 */
    
        /************************************************************************/
    
        vector<DMatch> matches;
    
        FlannBasedMatcher matcher;
    
        Mat image_match;
    
        matcher.match(description1, description2, matches);
    
        /************************************************************************/
    
        /* 下面计算向量距离的最大值与最小值 */
    
        /************************************************************************/
    
        double max_dist = 0, min_dist = 100;
    
        for (int i = 0; i < description1.rows; i++)
    
        {
    
            if (matches.at(i).distance>max_dist)
    
            {
    
                max_dist = matches[i].distance;
    
            }
    
            if (matches[i].distance<min_dist)
    
            {
    
                min_dist = matches[i].distance;
    
            }
    
        }
    
        cout << "最小距离为" << min_dist << endl;
    
        cout << "最大距离为" << max_dist << endl;
    
        /************************************************************************/
    
        /* 得到距离小于而V诶最小距离的匹配 */
    
        /************************************************************************/
    
        vector<DMatch> good_matches;
    
        for (int i = 0; i < matches.size(); i++)
    
        {
    
            if (matches[i].distance<2*min_dist)
    
            {
    
                good_matches.push_back(matches[i]);
    
                cout <<"第一个图中的"<< matches[i].queryIdx<<"匹配了第二个图中的"<<matches[i].trainIdx<<endl;
    
            }
    
        }
    
        drawMatches(input1, kerpoints1, input2, kerpoints2, good_matches, image_match);
    
        imshow("匹配后的图片", image_match);
    
        imwrite("匹配后的图片.png", image_match);
    
        cout << "匹配的特征点数为:" << good_matches.size() << endl;
    
        waitKey(0);
    
        return 0;
    
    }
    
    

    程序运行前的原始图片

    box.png box_in_scene.png

    提取特征点后

    box提取特征后.png box_in_scene提取特征后

    进行匹配后

    匹配特征后.png Paste_Image.png Paste_Image.png

    相关代码介绍

    
        double max_dist = 0, min_dist = 100;
    
        for (int i = 0; i < description1.rows; i++)
    
        {
    
            if (matches.at(i).distance>max_dist)
    
            {
    
                max_dist = matches[i].distance;
    
            }
    
            if (matches[i].distance<min_dist)
    
            {
    
                min_dist = matches[i].distance;
    
            }
    
        }  
    
    

    设置阈值,当特征向量的距离在最小距离的二倍范围内的,匹配为好的匹配;

    本博文由时尚时尚最时尚的markdown编辑器编写.

    相关文章

      网友评论

        本文标题:3. opencv提取SIFT特征

        本文链接:https://www.haomeiwen.com/subject/hqjfqttx.html