opencv(31)---SIFT特征匹配

SIFT特征提取匹配

步骤

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

函数原型

这里写图片描述

代码片段

这里写图片描述

使用匹配器进行匹配

原理

暴力匹配器很简单, 首先在第一幅图像中选取一个关键点然后依次与第二幅图像的每个关键点进行(描述符)距离测试, 最后返回距离最近的关键点

函数原型1- - -BFMatcher

这里写图片描述

  • normType: 用于指定要使用的距离测试类型, 默认值NORM_L2, L1和L2较适用SIFT和SUFT算法
  • crossCheck: 是否交叉检测, 默认值false(不使用)。如果设置为true, 匹配条件就会更加严格, 只有到A中的第i个特征点与B中的第j个特征点距离最近, 并且B 中的第j个特征点到A中的第i个特征点也是最近(A中没有其他点到j的距离更近)时才会返回最佳匹配(i, j), 也就是这两个特征点要互相匹配才行

函数原型2–match

这里写图片描述

这里写图片描述

函数原型3- - -drawMatches

这里写图片描述

  • img1: 输入的第一幅图像
  • keypoints1: 根据第一幅图像得到的特征点
  • img2: 输入的第二幅图像
  • keypoints2: 根据第二幅图像得到的特征点
  • matches1to2: 第一幅图像到第二幅图像的匹配点, 即表示每一个图1中的特征点都能在图2中有一一对应的点
  • outImg: 输出图像, 包含匹配结果, 与flags参数有关
  • matchColor: 匹配的输出颜色, 即匹配到的线和关键点的颜色, 默认值Scalar::all(-1)
  • singlePointColor: 单一特征点的颜色, 默认值Scalar::all(-1)
  • matchesMask: 确定哪些匹配是要绘制出来的掩码, 为空则所有匹配都绘制
  • flags: 特征绘制的标识符, 默认值DrawMatchesFlags::DEFAULT, 可以在下面选:

应用实例

这里写图片描述

代码1- - -SIFT_BFMATCH的第一种方式

#include "opencv2/opencv.hpp"
#include <opencv2/nonfree/nonfree.hpp>
#include <opencv2/legacy/legacy.hpp>
#include <vector>
#include<iostream>
using namespace std;
using namespace cv;

void main()
{    
    Mat srcImg1 = imread("11.jpg");
    Mat srcImg2 = imread("22.jpg");
    //定义SIFT特征检测类对象
    SiftFeatureDetector siftDetector1;
    SiftFeatureDetector siftDetector2;
    //定义KeyPoint变量
    vector<KeyPoint>keyPoints1;
    vector<KeyPoint>keyPoints2;
    //特征点检测
    siftDetector1.detect(srcImg1, keyPoints1);
    siftDetector2.detect(srcImg2, keyPoints2);
    //绘制特征点(关键点)
    Mat feature_pic1, feature_pic2;
    drawKeypoints(srcImg1, keyPoints1, feature_pic1, Scalar::all(-1));
    drawKeypoints(srcImg2, keyPoints2, feature_pic2, Scalar::all(-1));
    //drawKeypoints(srcImg1, keyPoints1, feature_pic1, Scalar(0, 255, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
    //drawKeypoints(srcImg2, keyPoints2, feature_pic2, Scalar(0, 255, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
    //显示原图
    imshow("src1", srcImg1);
    imshow("src2", srcImg2);
    //显示结果
    imshow("feature1", feature_pic1);
    imshow("feature2", feature_pic2);

    //计算特征点描述符 / 特征向量提取
    SiftDescriptorExtractor descriptor;
    Mat description1;
    descriptor.compute(srcImg1, keyPoints1, description1);
    Mat description2;
    descriptor.compute(srcImg2, keyPoints2, description2);
    cout<<description1.cols<<endl;
    cout<<description1.rows<<endl;

    //进行BFMatch暴力匹配
    BruteForceMatcher<L2<float>>matcher;    //实例化暴力匹配器
    vector<DMatch>matches;   //定义匹配结果变量
    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.at(i).distance < min_dist)
            min_dist = matches[i].distance;
    }
    cout<<"min_distance="<<min_dist<<endl;
    cout<<"max_distance="<<max_dist<<endl;

    //匹配结果删选    
    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]);
    }

    Mat result;
    drawMatches(srcImg1, keyPoints1, srcImg2, keyPoints2, good_matches, result,  Scalar(0, 255, 0), Scalar::all(-1));
    imshow("Match_Result", result);

    waitKey(0);
}

代码2- - -sift_BFMatch的第二种方式

#include "opencv2/opencv.hpp"
#include <opencv2/nonfree/nonfree.hpp>
#include <opencv2/legacy/legacy.hpp>
#include <vector>
#include<iostream>
using namespace std;
using namespace cv;

void main()
{    
    Mat srcImg1 = imread("00.jpg");
    Mat srcImg2 = imread("01.jpg");
    //定义SIFT特征检测类对象
    SiftFeatureDetector siftDetector1;
    SiftFeatureDetector siftDetector2;
    //定义KeyPoint变量
    vector<KeyPoint>keyPoints1;
    vector<KeyPoint>keyPoints2;
    //特征点检测
    siftDetector1.detect(srcImg1, keyPoints1);
    siftDetector2.detect(srcImg2, keyPoints2);
    //绘制特征点(关键点)
    Mat feature_pic1, feature_pic2;
    drawKeypoints(srcImg1, keyPoints1, feature_pic1, Scalar::all(-1));
    drawKeypoints(srcImg2, keyPoints2, feature_pic2, Scalar::all(-1));
    //drawKeypoints(srcImg1, keyPoints1, feature_pic1, Scalar(0, 255, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
    //drawKeypoints(srcImg2, keyPoints2, feature_pic2, Scalar(0, 255, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
    //显示原图
    imshow("src1", srcImg1);
    imshow("src2", srcImg2);
    //显示结果
    imshow("feature1", feature_pic1);
    imshow("feature2", feature_pic2);

    //计算特征点描述符 / 特征向量提取
    SiftDescriptorExtractor descriptor;
    Mat description1;
    descriptor.compute(srcImg1, keyPoints1, description1);
    Mat description2;
    descriptor.compute(srcImg2, keyPoints2, description2);
    cout<<description1.cols<<endl;
    cout<<description1.rows<<endl;

    //进行BFMatch暴力匹配
    BruteForceMatcher<L2<float>>matcher;    //实例化暴力匹配器
    vector<DMatch>matches;  //定义匹配结果变量
    matcher.match(description1, description2, matches);  //实现描述符之间的匹配

    //匹配结果删选    
    std::nth_element(matches.begin(), matches.begin()+29, matches.end());   //提取出前30个最佳匹配结果     
    matches.erase(matches.begin()+30, matches.end());    //剔除掉其余的匹配结果

    Mat result;
    //drawMatches(srcImg1, keyPoints1, srcImg2, keyPoints2, matches, result, Scalar::all(-1), Scalar::all(-1));
    drawMatches(srcImg1, keyPoints1, srcImg2, keyPoints2, matches, result,  Scalar(0, 255, 0), Scalar::all(-1));
    imshow("Match_Result", result);

    waitKey(0);
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值