特征匹配中OpenCV Dmatch类的用法解析以及非常详细的ORB特征提取与匹配解析

2023-05-16

首先说明一点,在SLAM中进行特征提取和匹配时,需要注意使用的OpenCV版本,在使用OpenCV2.x版本时,可以创建特征对象如下所示(省略了参数表):

ORB orb;
SURF surf;
SIFT sift;

orb.detect();
sift.detect();
surf.detect();

但是OpenCV3.X中就不允许这么做了,这是因为,opencv3.0直接使用 ORB orb时,ORB里面没有构造方法,只有一个静态的create。所以特征提取时,就只能使用以下方式:

Ptr orb=ORB::create()//参数表省略了,具体可查看官方文档,或者输入VS2015等IDE看智能提示;

下面重点说一下,DMatch类,在OpenCV2.x中Dmatch为结构体数据类型,在OpenCV3.x中为Class类型。在OpenCV3.x中的定义为:

class CV_EXPORTS_W_SIMPLE DMatch
{
public:
    CV_WRAP DMatch();
    CV_WRAP DMatch(int _queryIdx, int _trainIdx, float _distance);
    CV_WRAP DMatch(int _queryIdx, int _trainIdx, int _imgIdx, float _distance);

    CV_PROP_RW int queryIdx; // query descriptor index
    CV_PROP_RW int trainIdx; // train descriptor index
    CV_PROP_RW int imgIdx;   // train image index

    CV_PROP_RW float distance;

    // less is better
    bool operator<(const DMatch &m) const;
};

一个匹配器尝试在一副或一组图中匹配一幅图中的关键点,如果匹配成功,将返回 cv::DMatch 的列表,说人话:Dmatch对象保存的是匹配成功的结果,当然这个匹配结果里面包含了不少的误匹配

成员说明:

queryIdx : 查询点的索引(当前要寻找匹配结果的点在它所在图片上的索引).

trainIdx : 被查询到的点的索引(存储库中的点的在存储库上的索引)
distance: 为两个描述子之间的距离
举个例子:下面给出提取ORB特征并进行匹配的过程(基于OpenCV3.2),以及DMatch对象的用法。下面使用的两张图盘我就不上传了,随便找一张图片,然后截图一部分当做另一张图片,一般而言,截图出来的那部分图片,当做第一张,也就是train,完整的是第二张也就是query。运行环境:VS2015+OpenCV3.2.0

#include <iostream>
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
	Mat obj = imread("1.jpg");   //载入目标图像
	Mat scene = imread("2.jpg"); //载入场景图像
	if (obj.empty() || scene.empty())
	{
		cout << "Can't open the picture!\n";
		return 0;
	}
	vector<KeyPoint> obj_keypoints, scene_keypoints;
	Mat obj_descriptors, scene_descriptors;
	//ORB detector;     //采用ORB算法提取特征点
	//ORB orb;
	Ptr<ORB> detector = ORB::create(500, 1.2f, 8, 31, 0, 2, ORB::HARRIS_SCORE, 31, 20);
	detector->detect(obj, obj_keypoints);
	detector->detect(scene, scene_keypoints);
	detector->compute(obj, obj_keypoints, obj_descriptors);
	detector-> compute(scene, scene_keypoints, scene_descriptors);
	BFMatcher matcher(NORM_HAMMING, true); //汉明距离做为相似度度量
	
	//匹配结果放在matches里面
	vector<DMatch> matches;
	matcher.match(obj_descriptors, scene_descriptors, matches);//匹配成功的点对数为257,
	
	//按照匹配关系将图画出来,背景图为match_img
	Mat match_img;
	drawMatches(obj, obj_keypoints, scene, scene_keypoints, matches, match_img);
	imshow("滤除误匹配前", match_img);

	//保存匹配对序号
	vector<int> queryIdxs(matches.size()), trainIdxs(matches.size());
	for (size_t i = 0; i < matches.size(); i++)
	{
		queryIdxs[i] = matches[i].queryIdx;//取出查询图片中匹配的点对的索引即id号;那么queryIdxs、trainIdxs都为257
		trainIdxs[i] = matches[i].trainIdx;//取出训练图片中匹配的点对的索引即id号;
	}

	Mat H12;   //变换矩阵

	vector<Point2f> points1; 
	KeyPoint::convert(obj_keypoints, points1, queryIdxs);//KeyPoint根据索引转point2f坐标
	vector<Point2f> points2; 
	KeyPoint::convert(scene_keypoints, points2, trainIdxs);//同上
	int ransacReprojThreshold = 3;  //拒绝阈值

	cout << "matches size = " << matches.size() << endl;
	H12 = findHomography(Mat(points1), Mat(points2), CV_RANSAC, ransacReprojThreshold);//计算单应矩阵
	vector<char> matchesMask(matches.size(), 0);//用于内点标记使用
	Mat points1t;
	perspectiveTransform(Mat(points1), points1t, H12);//对输入二维点做透视变换,变换后的结果保存在points1t中
	for (size_t i1 = 0; i1 < points1.size(); i1++)  //保存‘内点’
	{
		if (norm(points2[i1] - points1t.at<Point2f>((int)i1, 0)) <= ransacReprojThreshold) //给内点做标记
		{
			matchesMask[i1] = 1;
		}
	}
	Mat match_img2;   //滤除‘外点’后
	drawMatches(obj, obj_keypoints, scene, scene_keypoints, matches, match_img2, Scalar(0, 0, 255), Scalar::all(-1), matchesMask);

	//画出目标位置
	std::vector<Point2f> obj_corners(4);
	obj_corners[0] = cvPoint(0, 0); obj_corners[1] = cvPoint(obj.cols, 0);
	obj_corners[2] = cvPoint(obj.cols, obj.rows); obj_corners[3] = cvPoint(0, obj.rows);
	std::vector<Point2f> scene_corners(4);
	perspectiveTransform(obj_corners, scene_corners, H12);
	line(match_img2, scene_corners[0] + Point2f(static_cast<float>(obj.cols), 0),
		scene_corners[1] + Point2f(static_cast<float>(obj.cols), 0), Scalar(0, 0, 255), 2);
	line(match_img2, scene_corners[1] + Point2f(static_cast<float>(obj.cols), 0),
		scene_corners[2] + Point2f(static_cast<float>(obj.cols), 0), Scalar(0, 0, 255), 2);
	line(match_img2, scene_corners[2] + Point2f(static_cast<float>(obj.cols), 0),
		scene_corners[3] + Point2f(static_cast<float>(obj.cols), 0), Scalar(0, 0, 255), 2);
	line(match_img2, scene_corners[3] + Point2f(static_cast<float>(obj.cols), 0),
		scene_corners[0] + Point2f(static_cast<float>(obj.cols), 0), Scalar(0, 0, 255), 2);

	imshow("滤除误匹配后", match_img2);
	waitKey(0);

	return 0;
}

本身对上述代码中Dmatch理解并不透彻,于是进行了单步调试:
运行至43行时,结果如下:
运行结果
看出两幅图的匹配点对数为257对:第一对匹配点为:查询图片的第1个特征点匹配训练图片的第231个特征点,4-264,5-307,7-92,等等等等。
这样就可以取出匹配点对的id,继而进行下一步操作。
有需要的话,再继续讲下去。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

特征匹配中OpenCV Dmatch类的用法解析以及非常详细的ORB特征提取与匹配解析 的相关文章

  • 相机标定原理

    cnblogs上的这篇讲相机标定的博文值得一看 csdn上这篇也可以参考 相机标定基础知识 相机标定技术涉及到一些数学原理和几何模型 xff0c 这些数学原理和几何模型是相机标定算法使用和进一步发展的基础 下面对相机标定技术中涉及到的齐次坐
  • VS Code的Git插件

    Visual Studio Code是微软公司推出的一款跨平台代码编辑 Edit 编译 Build 调试 Debug 工具 笔者认为其相当于是Sublime Text这款代码编辑器的升级版 集成了丰富的插件 xff0c 包括代码管理中极为常
  • Ubuntu缺少libncurses.so.5的解决办法

    执行arm none eabi gdb时候出错 xff1a arm none eabi gdb error while loading shared libraries libncurses so 5 cannot open shared
  • freeRTOS的任务抢占和时间片轮转

    实时操作系统的一个特点就是可以任务抢占 xff0c 高优先级的任务可以抢占比自己优先级低的任务 xff0c 如果新任务优先级和当前人任务优先级一样 xff0c 且在使能了时间片的方式的话 xff0c 二者以时间片的方式共享cpu xff0c
  • RH850 F1L freeRTOS 任务栈的切换

    pxCurrentTCB指向的任务块中 xff0c 有2个和栈相关的变量pxTopOfStack和pxStack pxTopOfStack指向当前堆栈栈顶 xff0c 随着进栈出栈 xff0c pxTopOfStack指向的位置是会变化的
  • opencv 3.0 图像去畸变 undistortion

    主要用到的是 initUndistortRectif yMap这个函数 在opencv中这个函数是用于 去除镜头畸变的图像拉伸 为了快速算法 xff1a 使用了坐标查找变和双线性差值的方法 先上结果图 原图 去畸变至全图 去畸变并保留最大图
  • 多传感器融合MSF算法源码阅读(三)

    文章目录 1 触发测量更新回调函数2 测量更新状态量3 总结 无人驾驶算法学习 xff08 六 xff09 xff1a 多传感器融合MSF算法 多传感器融合MSF算法源码阅读 一 多传感器融合MSF算法源码阅读 二 1 触发测量更新回调函数
  • 视觉VIO:S-MSCKF算法学习(一)

    文章目录 1 算法简介2 算法调试3 代码解读3 1 前端 ImageProcessor3 2 后端 Msckf Vio 1 算法简介 Mingyang Li博士于2007年提出MSCKF Multi State Constraint Ka
  • 无人驾驶算法学习(六):多传感器融合MSF算法

    文章目录 1 引言2 算法理论2 1 MSF基本模型2 2 预测2 3 测量与更新 3 核心代码分析4 代码实战 1 引言 本文的多传感器融合是建立在读懂 Quaternion kinematics for the error state
  • 多传感器融合MSF算法源码阅读(一)

    文章目录 1 代码框架1 1代码调用关系图 1 2主要函数调用关系图 2 posemsf阅读2 1程序入口 xff1a 2 2PoseSensorManager类 1 代码框架 论文解读 无人驾驶算法学习 xff08 六 xff09 xff
  • 通过launch文件修改订阅话题的两个操作

    文章目录 1 引言2 利用param修改话题2 利用remap修改话题 1 引言 在调试程序中需要经常修改订阅的话题 如果直接修改每次都要编译 在大型项目中这是难以想象的 所以利用launch中的param机制 通过修改launch文件进行
  • ubuntu下安装vnc出错(灰屏)

    我 win10 用的 vncviewer exe xff0c 在Ubuntu上首先需要安装vnc4server apt get install vnc4server 出现灰色屏幕和 型鼠标是因为vncserver找不到指定的图形化组件 xf
  • 51UWB单片机连接ESP8266实现Wifi接收串口数据

    UWB定位需要电脑读取UWB基站的串口数据来读取距离信息 xff0c 用wifi连接可以实现远程接收串口数据方便连接 这里记录一下如何让51UWB单片机接入WiFi模块ESP8266 前置条件 xff1a 单片机完成基站 xff08 RX
  • Qt中的三种基类

    一 QMainWindow xff1a QMainWindow类提供一个带有菜单条 xff0c 工具条和一个状态条的主应用程序窗口 主窗口通常提供一个大的中央窗口部件 xff0c 以及周围菜单 xff0c 工具条 xff0c 和一个状态栏
  • 如何理解强化学习中迭代线性-二次型调节器(ILQR)算法

    1 强化学习预备知识 xff08 1 xff09 状态 动作价值函数Q s a xff1a 在状态s xff0c 先立即执行动作a xff0c 后面所有的状态都按照最优动作进行执行 xff0c 所能获得价值之和 xff1b xff08 2
  • 字符串中字符查找函数:strchr,wcschr 及strrchr, wcsrchr函数

    xff08 1 xff09 char strchr const char string int c wchar t wcschr const wchar t string wchar t c Find a character in a st
  • C#中委托和事件的区别

    言简意赅的解释 先说总结 xff1a 事件就是委托链 xff08 也就是继承自MulticastDelegate类的委托 xff0c 用delegate声明的委托就是继承自MulticastDelegate类的 xff09 的属性 xff0
  • 采用python对基于moveit的机械臂不同功能操作

    此处对于机械臂的操作是实例类MoveGroupCommander xff08 是一个接口类 xff09 xff0c 其父类是move group xff0c 基本的关系大概就是这样的 类的继承关系如下 xff1a moveit的操作 xff
  • Gazebo系列教程 <构建一个机器人 2.2> 修改模型的外观与添加传感器

    1 修改模型外观 当sdf文件修改后然后保存 xff0c 在gazebo中insert时会自动更新模型文件 xff0c 所以在模型文件修改后 xff0c 不需要关闭然后再重新打开gazebo的 大概的意思就是将某个模型的外观属性 xff08
  • Gazebo系列教程< 构建一个机器人 2.3> 添加夹爪,并组成带有夹爪与传感器的小车

    1 制作一个夹爪 本文介绍通过sdf的编辑 xff0c 实现两指的简单夹爪 1 1制作模型 xff08 1 xff09 新建一个文件夹 mkdir simple gripper tutorial cd simple gripper tuto

随机推荐

  • vslam: 扫盲之旅

    ICCV研讨会 xff1a 实时SLAM的未来以及深度学习与SLAM的比较 http blog csdn net qq 18661939 article details 51919329 The Future of Real time SL
  • RLException: [XXX] is neither a launch file in package [XXX] nor is [XXX] a launch file name报错信息解决方法

    在运行roslaunch时出现了类似下面的错误 xff1a RLException mav hovering example launch is neither a launch file in package rotors gazebo
  • python音频播放问题解决方法

    获取音频 只是为了验证问题存在 xff0c 所以就提供了一个获取音频的方法 xff0c 就是白嫖了 根据有道翻译的发音获取到地址 xff1a https dict youdao com dictvoice le 61 auto amp au
  • 【随笔】Ubuntu远程桌面+Docker显示问题记录

    场景 xff1a 两台Linux主机 B主机需要远程桌面到A主机上运行程序 xff0c 需要运行的程序是跑在A主机的Docker里面的 需要实现的效果就是 xff0c A主机分一些资源给B主机来跑程序 xff0c B在跑程序的时候不能影响A
  • 树莓派4B SD卡烧录、安装 ubuntu mate 20.04 教程

    系统安装 一 下载系统镜像 默认是在树莓派4B上安装ubuntu mate系统 xff0c 当然可以安装其他的系统 xff0c 这里不做介绍 Ubuntu MATE是Ubuntu Linux官方的一个派生版 xff0c 基于桌面环境MATE
  • Movidus 神经计算棒 树莓派平台 ncsdk2.0 完全配置 及 一些问题

    配置之前的琐事和解决方法 之前配置了的1 x版本的ncsdk 错误百出 xff0c 于是有了另一篇文章就是纯API配置 xff0c 没有配完全版 经过我的测试 xff0c 用以下方法配置是可以用的 配置方法和下面的2 0类似 xff0c 不
  • 小猫爪:PMSM之FOC控制12-扩展卡尔曼滤波状态观测器解析

    小猫爪 xff1a PMSM之FOC控制12 扩展卡尔曼滤波状态观测器解析 1 前言2 卡尔曼滤波的原理2 1 卡尔曼滤波的思想2 2 卡尔曼滤波的过程 3 卡尔曼滤波和观测器的联系3 1 观测器的引入3 2 卡尔曼滤波在观测器的体现 4
  • git怎么合并两个分支

    git怎么合并分支代码 1 git 命令 注意 第一步你得把当前分支合到远程分支去才能有下面的操作 另外我是将develop分支代码合并到release分支去 1 推完代码到远程仓库查看本地分支 如果推错分支代码那么请将分支切到刚刚推送上去
  • 小猫爪:嵌入式小知识11-MPU详解及其应用

    小猫爪 xff1a 嵌入式小知识11 MPU详解及其应用 1 前言2 MPU简介3 MPU相关概念3 1 Memory Map3 2 MPU Region3 3 Region优先级3 4 Background Region3 5 Cache
  • MavSDK&Mavros学习笔记

    MavSDK amp Mavros学习笔记 Introduction MAVSDK Guide mavlink io GitHub mavlink MAVSDK源码 C 43 43 MAVSDK API reference paper Gi
  • Ubuntu realsenseSDK2安装方法

    分为两种 xff0c 这里只是Intel的翻译和个人安装记录总结 详细可以参看Intel realsenseSDK2的github仓库Release Intel RealSense SDK 2 0 v2 51 1 IntelRealSens
  • ROS☞通过两种方法提取.bag中的图像数据

    以下两种环境均在Ubuntu16 04环境下测试成功 第一种方法 ROS 从rosbag中提取图像 xff08 by launch文件 xff09 1 新建launch文件 xff08 文件在哪无所谓 xff0c 可以在catkin ws的
  • Git基础教程(二)

    使用Git删除文件 1 直接删除 可以使用rm命令删除文件 xff0c 如 xff1a rm welcome html 然后查看一下状态 xff1a 然后发现welcome html的状态为deleted xff0c 如果你真的想在git管
  • Git基础教程(三)

    Git分支 在git中使用分支非常简单 xff0c 只需要使用Git branch命令即可 xff1a git branch test 新建test分支 此时使用git branch查看一下分支 xff1a 此时的确多了一个分支 xff0c
  • Git基础教程(四)

    工作做到一半需要临时切换到别的任务 1 先commit当前的进度 简单的做法先保存当前的修改 然后切换到有问题的分级 xff0c 先完成别的功能 xff0c 然后切换回原来做到一半的develop分支 xff0c 执行reset命令 xff
  • jupyter notebook matplotlib绘制动态图并显示在notebook中

    有些时候matplotlib 的绘图没法显示在notebook中 xff0c 或者显示不了 这与backend有关 首先启动你的notebook xff0c 输入 pylab 查看你的matplotlib后端 xff0c 我的输出为 xff
  • 主机连接wifi,如何设置虚拟机上网方式

    主机是windows系统 xff08 win7 xff0c win10 xff09 xff0c 如果使用wifi上网 xff0c 虚拟机如何设置 xff1f xff1f 首先打开主机网络 xff08 如下所示 xff09 xff1a 1 点
  • VS2015断点调试方法

    备注 xff1a 部分图片 xff08 打马赛克的 xff09 转自百度 xff0c 侵删 xff01 果真被和谐了 xff0c 大家还是看这个网页吧 xff1a https jingyan baidu com album e75057f2
  • FreeRTOS 源代码的编程标准与命名约定

    一 编程标准 xff08 Coding Standard xff09 FreeRTOS 源代码遵守 MISRA Motor Industry Software Reliability Association 规范 与 MISRA 标准有出入
  • 特征匹配中OpenCV Dmatch类的用法解析以及非常详细的ORB特征提取与匹配解析

    首先说明一点 xff0c 在SLAM中进行特征提取和匹配时 xff0c 需要注意使用的OpenCV版本 xff0c 在使用OpenCV2 x版本时 xff0c 可以创建特征对象如下所示 xff08 省略了参数表 xff09 xff1a OR