OpenCV4.x图像处理实例- 特征描述符匹配器及匹配点绘制

第二节 特征描述符匹配器及匹配点绘制

OpenCV中关键点描述符的匹配器具有带有公共接口的包装器,可以轻松地在解决同一问题的不同算法之间进行切换。 本节专门介绍在多维空间中以向量表示的匹配描述符。 实现矢量描述符匹配器的所有对象都继承DescriptorMatcher接口以及相应的关键点和匹配点绘制接口。

1、cv::drawKeypoints


绘制关键点

void cv::drawKeypoints(InputArray image,const std::vector< KeyPoint > & keypoints,InputOutputArray outImage,const Scalar & color = Scalar::all(-1),DrawMatchesFlags flags = DrawMatchesFlags::DEFAULT)

参数如下:

参数名称 参数描述
image 原图像
keypoints 原图像的关键点
outImage 输出图像。 其内容取决于标志值,该标志值定义在输出图像中绘制的内容。 请参阅下面的可能的标志位值。
color 关键点的颜色。
flags 标志设置图形功能。 可能的标志位值由DrawMatchesFlags定义。 请参阅上述drawMatches中的详细信息。

2、cv::drawMatches


从两个图像绘制找到的关键点匹配项。

void cv::drawMatches(InputArray img1,const std::vector< KeyPoint > & keypoints1,InputArray img2,const std::vector< KeyPoint > & keypoints2,const std::vector< DMatch > & matches1to2,InputOutputArray outImg,const Scalar & matchColor = Scalar::all(-1),const Scalar & singlePointColor = Scalar::all(-1),const std::vector< char > & matchesMask = std::vector< char >(),DrawMatchesFlags flags = DrawMatchesFlags::DEFAULT)

参数如下:

参数名称 参数描述
img1 第一个源图像
keypoints1 第一个源图像关键点
img2 第二个源图像
keypoints2 第二个源图像关键点
matches1to2 从第一张图片匹配到第二张图片,这意味着keypoints1 [i]在keypoints2 [matches [i]]中具有一个对应点。
outImg 输出图像。 其内容取决于标志值,该标志值定义在输出图像中绘制的内容。 请参阅下面的可能的标志位值。
matchColor 匹配项的颜色(线和连接的关键点)。 如果matchColor == Scalar :: all(-1),则颜色是随机生成的。
singlePointColor 单个关键点(圆圈)的颜色,这意味着关键点没有匹配项。 singlePoint Color == Scalar :: all(-1)的颜色是随机生成的。
matchesMask 遮罩确定绘制哪些匹配项。 如果蒙版为空,则绘制所有匹配项。
flags 标志设置图形功能。 可能的标志位值由DrawMatchesFlags定义。

3、cv::BFMatcher


蛮力(Brute-force)描述符匹配器。对于第一组中的每个描述符,此匹配器通过尝试每个描述符来找到第二组中最接近的描述符。 此描述符匹配器支持屏蔽描述符集的允许匹配。

类BFMatcher继承DescriptorMatcher接口,并实现了相应的方法,创建BFMatcher对象通过静态的create方法来实现。

static Ptr cv::BFMatcher::create (int normType=NORM_L2,bool crossCheck = false)

参数如下:

参数名称 参数描述
normType NORM_L1,NORM_L2,NORM_HAMMING,NORM_HAMMING2中的一个。 对于SIFT和SURF描述符,L1和L2norms是更好的选择,当WTA_K == 3或4时,NORM_HAMMING应该与ORB,BRISK和Brief一起使用,NORM_HAMMING2应该与ORB一起使用(请参阅ORB :: ORB构造函数说明)。
crossCheck 如果为false,则为每个查询描述符找到k个最近的邻居时,这将是默认的BFMatcher行为。 如果crossCheck == true,则k = 1的knnMatch()方法将仅返回对(i,j),这样对于第i个查询描述符,匹配器集合中的第j个描述符是最近的,反之亦然,即 BFMatcher将仅返回一致对。 当有足够的匹配项时,这种技术通常会以最少的异常值产生最佳结果。 这是D. Lowe在SIFT论文中使用的比率测试的替代方法。

DescriptorMatcher接口有几个核心的接口:

  • void cv::DescriptorMatcher::match(InputArray queryDescriptors,InputArray trainDescriptors,std::vector< DMatch > & matches,InputArray mask = noArray())

  • void cv::DescriptorMatcher::radiusMatch(InputArray queryDescriptors,InputArray trainDescriptors,std::vector< std::vector< DMatch > > & matches,float maxDistance,InputArray mask = noArray(),bool compactResult = false)

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;

int main()
{
    // 读取图像
    cv::Mat src1 = cv::imread("images/plane.jpg");
    if(src1.empty()){
        cerr << "cannot read image 1.\n";
        return EXIT_FAILURE;
    }
    cv::Mat src2 = cv::imread("images/plane_part.jpg");
    if(src2.empty()){
        cerr << "cannot read image 2.\n";
        return EXIT_FAILURE;
    }

    // 转换成灰度图像
    cv::Mat gray1,gray2;
    cv::cvtColor(src1,gray1,cv::COLOR_BGR2GRAY);
    cv::cvtColor(src2,gray2,cv::COLOR_BGR2GRAY);

    // 创建SIFT特征提取器
    cv::Ptr<cv::SIFT> sift = cv::SIFT::create(256,3,0.09,220,2.5);

    // 特征点检测
    // 检测特征点
    vector<cv::KeyPoint> keypoints1,keypoints2;
    cv::Mat descriptor1,descriptor2;
    sift->detectAndCompute(gray1,cv::Mat(),keypoints1,descriptor1);
    sift->detectAndCompute(gray2,cv::Mat(),keypoints2,descriptor2);

    // 创建特征点匹配器
    cv::Ptr<cv::BFMatcher> matcher = cv::BFMatcher::create();

    // 执行特征点匹配
    vector<cv::DMatch> dmatch;
    matcher->match(descriptor1,descriptor2,dmatch);

    // 绘制特征点和匹配特征结果
    cv::Mat matchResult;
    cv::drawMatches(src1,keypoints1,src2,keypoints2,dmatch,matchResult);
    cv::imshow("src1",src1);
    cv::imshow("src2",src2);
    cv::imshow("match result",matchResult);
    cv::waitKey();
    return 0;
}

在这里插入图片描述
在这里插入图片描述

4、cv::FlannBasedMatcher


基于Flann的描述符匹配器。该匹配器在火车描述符集合上训练cv :: flann :: Index,并调用其最近的搜索方法以找到最佳匹配。 因此,匹配大型火车集合时,此匹配器可能比蛮力匹配器更快。 FlannBasedMatcher不支持屏蔽描述符集的允许匹配,因为flann :: Index不支持此功能。

类FlannBasedMatcher继承DescriptorMatcher接口,并实现了相应的方法,创建BFMatcher对象通过静态的create方法来实现。

static Ptr cv::FlannBasedMatcher::create()

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;

int main()
{
    // 读取图像
    cv::Mat src1 = cv::imread("images/plane.jpg");
    if(src1.empty()){
        cerr << "cannot read image 1.\n";
        return EXIT_FAILURE;
    }
    cv::Mat src2 = cv::imread("images/plane_part.jpg");
    if(src2.empty()){
        cerr << "cannot read image 2.\n";
        return EXIT_FAILURE;
    }

    // 转换成灰度图像
    cv::Mat gray1,gray2;
    cv::cvtColor(src1,gray1,cv::COLOR_BGR2GRAY);
    cv::cvtColor(src2,gray2,cv::COLOR_BGR2GRAY);

    // 创建SIFT特征提取器
    cv::Ptr<cv::SIFT> sift = cv::SIFT::create(256,3,0.09,220,2.5);

    // 特征点检测
    // 检测特征点
    vector<cv::KeyPoint> keypoints1,keypoints2;
    cv::Mat descriptor1,descriptor2;
    sift->detectAndCompute(gray1,cv::Mat(),keypoints1,descriptor1);
    sift->detectAndCompute(gray2,cv::Mat(),keypoints2,descriptor2);

    // 创建特征点匹配器
    cv::Ptr<cv::FlannBasedMatcher> matcher = cv::FlannBasedMatcher::create();

    // 执行特征点匹配
    vector<cv::DMatch> dmatch;
    matcher->match(descriptor1,descriptor2,dmatch);

    // 绘制特征点和匹配特征结果
    cv::Mat matchResult;
    cv::drawMatches(src1,keypoints1,src2,keypoints2,dmatch,matchResult);
    cv::imshow("src1",src1);
    cv::imshow("src2",src2);
    cv::imshow("match result",matchResult);
    cv::waitKey();
    return 0;
}

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/wujuxKkoolerter/article/details/114163008