OpenCV(四十六):特征点匹配

1.特征点匹配的定义

**特征点匹配是一种在两幅图像中寻找相互对应的特征点,并建立它们之间的对应关系的过程。**具体而言,首先通过特征检测算法在两幅图像中寻找相互对应的特征点,然后,对于每个特征点,通过描述子提取算法计算其描述子,最后,使用匹配算法对两组特征点的描述子进行比较,以找到相互匹配的特征点对。

2.DMatch() 用于表示特征点匹配的数据结构

cv::DMatch::DMatch ( int queryldx,

int _trainldx,

int _imgldx,

float _distance

)

  • queryIdx:查询描述子集合中的索引
  • trainIdx:训练描述子集合中的索引
  • imgldx:训练描述子来自的图像索引
  • distance:两个描述符之间的距离

3.特征点匹配类DescriptorMatcher的介绍

在OpenCV中,特征点匹配的类主要是cv::DescriptorMatcher。DescriptorMatcher是一个抽象基类,用于特征点描述子之间的匹配操作。

DescriptorMatcher类有以下常用方法和函数

1.match():对两组特征描述子进行匹配,返回匹配结果(DMatch对象的向量)。

void cv::DescriptorMatcher::match ( InputArray queryDescriptors,

InputArray trainDescriptors,

std::vector< DMatch > & matches,

InputArray mask = noArray()

)const

  • queryDescriptors:查询描述子集合
  • trainDescriptors: 训练描述子集合
  • matches:两个集合描述子匹配结果
  • mask:描述子匹配时的掩码矩阵,用于指定匹配哪些描述子
2.knnMatch():对两组特征描述子进行k近邻匹配,返回每个查询描述子的k个最佳匹配结果。

void cv::DescriptorMatcher::knnMatch ( InputArray queryDescriptors,

InputArray trainDescriptors,

std::vector< std::vector< DMatch > > & matches,

int k,

InputArray mask = noArray(),

bool compactResult = false

)const

  • queryDescriptors:查询描述子集合
  • trainDescriptors: 训练描述子集合
  • matches:描述子匹配结果
  • k:每个查询描述子在训练描述子集合中寻找的最优匹配结果的数目
  • mask:描述子匹配时的掩码矩阵,用于指定匹配哪些描述子。
  • compactResult:输出匹配结果数目是否与查询描述子数目相同的选择标志
3.radiusMatch():对两组特征描述子进行半径匹配,返回每个查询描述子在指定半径内的最佳匹配结果。

void cv::DescriptorMatcher::radiusMatch ( InputArray queryDescriptors,

InputArray trainDescriptors,

std::vector< std::vector< DMatch > > &matches,

float maxDistance,

InputArray mask = noArray(),

bool compactResult = false

)const

  • queryDescriptors:查询描述子集合
  • trainDescriptors: 训练描述子集合
  • matches:描述子匹配结果
  • maxDistance:两个描述子之间满足匹配条件的距离阀值
  • mask:描述子匹配时的掩码矩阵,用于指定匹配哪些描述子
  • compactResult:输出匹配结果数目是否与查询描述子数目相同的选择标志

4.特征点匹配函数BFMatcher()

BFMatcher():暴力匹配

cv::BFMatcher::BFMatcher ( int normType =ORM_L2,

bool crossCheck = false

)

  • normType:两个描述子之间距离的类型标志,可以选择的参数为NORM_LI、NORM_L2、NORM_HAMMING和NORM_HAMMING2。
  • crossCheck:是否进行交叉检测的标志。

5.显示特征点匹配结果函数drawMatches()

void cv::drawMatches ( InputArray img1,

const std::vector< KeyPoint > & keypoints1,

InputArray img2,

const std::vector< KeyPoint > & keypoints2,

const std::vector< DMatch > &matches1to2,

InputOutputArray outlmg,

const Scalar & matchColor = scalar: :all(-1),

const Scalar & singlePointColor = scalar: :all(-1),

const std::vector<char>& matchesMask = std: :vector< char >(),

DrawMatchesFlags flags = DrawMatchesFlags: :DEFAULT

)

  • imgl:第一张图像。
  • keypointsl:第一张图像中的关键点
  • img2:第二张图像。
  • keypoints2:第二张图像中的关键点。
  • matcheslto2:第一张图像中关键点与第二张图像中关键点的匹配关系。
  • outImg:显示匹配结果的输出图像。
  • matchColor:连接线和关键点的颜色。
  • singlePointColor: 没有匹配点的关键点的颜色
  • matchesMask:匹配掩码
  • flags:绘制功能选择标志

6.示例代码

复制代码
void orb_fearures(Mat &gray,vector<KeyPoint> &keypoints,Mat &descriptions){
    Ptr<ORB> orb=ORB::create(1000,1.2f);
    orb->detect(gray,keypoints);
    orb->compute(gray,keypoints,descriptions);
}
void Matcher_f(Mat img1,Mat img2){
    //提取特征点
    vector<KeyPoint> keypoints1,keypoints2;
    Mat descriptions1,descriptions2;
    //计算特征点
    orb_fearures(img1,keypoints1,descriptions1);
    orb_fearures(img2,keypoints2,descriptions2);
    //特征点匹配
    vector<DMatch> matches;//定义存放匹配结果的变量
    BFMatcher matcher(NORM_HAMMING);//定义特征点匹配的类,使用汉明距离
    matcher.match(descriptions1,descriptions2,matches);//进行特征点匹配
    ostringstream ss;
    ss<<"matches="<<matches.size()<<endl;//匹配成功特征点数目
    //通过汉明距离删选匹配结果
    double min_dist=1000,max_dist=0;
    for(int i=0;i<matches.size();i++){
        double dist=matches[i].distance;
        if(dist<min_dist) min_dist=dist;
        if(dist>max_dist) max_dist=dist;
    }
    //输出所有匹配结果中最大韩明距离和最小汉明距离
    ss<<"min_dist="<<min_dist<<endl;
    ss<<"max_dist="<<max_dist<<endl;
    //将汉明距离较大的匹配点对删除
    vector<DMatch> good_matches;
    for(int i=0;i<matches.size();i++){
        if(matches[i].distance<=max(2*min_dist,20.0)){
            good_matches.push_back(matches[i]);
        }
    }
    ss<<"good_min="<<good_matches.size()<<endl;//剩余特征点数目
    LOGD("%s",ss.str().c_str());

    //绘制匹配结果
    Mat outimg,outimg1;
    drawMatches(img1,keypoints1,img2,keypoints2,matches,outimg);
    drawMatches(img1,keypoints1,img2,keypoints2,good_matches,outimg1);

    //显示结果
    imwrite("/sdcard/DCIM/outimg.png",outimg);//未筛选结果
    imwrite("/sdcard/DCIM/outimg1.png",outimg1);//最小汉明距离筛选

}

未筛选的特征点匹配结果 :

最小汉明距离筛选特征点匹配结果:

相关推荐
孤廖3 分钟前
从 “模板” 到 “场景”,用 C++ 磨透拓扑排序的实战逻辑
开发语言·c++·程序人生·算法·贪心算法·动态规划·学习方法
老歌老听老掉牙13 分钟前
OpenCascade几何建模:平面创建与法向拉伸的工程实现
c++·平面·opencascade
理智的煎蛋18 分钟前
GPU 服务器压力测试核心工具全解析:gpu-burn、cpu-burn 与 CUDA Samples
运维·服务器·人工智能·压力测试·gpu算力
陈敬雷-充电了么-CEO兼CTO20 分钟前
视频理解新纪元!VideoChat双模架构突破视频对话瓶颈,开启多模态交互智能时代
人工智能·chatgpt·大模型·多模态·世界模型·kimi·deepseek
-凌凌漆-26 分钟前
【Qt】【C++】虚析构函数及 virtual ~Base() = default
java·c++·qt
simodai36 分钟前
机器学习1.Anaconda安装+环境配置
人工智能·机器学习
IT_陈寒42 分钟前
JavaScript 2024:10个颠覆你认知的ES新特性实战解析
前端·人工智能·后端
ModelWhale1 小时前
AI教育白皮书解读 | 医学教育数智化转型新机遇,“人工智能+”行动实践正当时
人工智能·ai
大模型真好玩1 小时前
大模型工程面试经典(五)—大模型微调与RAG该如何选?
人工智能·面试·deepseek
励志不掉头发的内向程序员1 小时前
STL库——AVL树
开发语言·c++·学习