opencv上gpu版surf特征点与orb特征点提取及匹配实例

2023-05-16

一、前言

本文主要实现了使用opencv里的gpu版surf特征检测器和gpu版orb检测器,分别对图片进行特征点提取及匹配,并对寻获的特征点进行了距离筛选,将匹配较为好的特征点进行展示

二、实现代码

我不生产代码,我只是代码的搬运工和修改

//main.cpp//
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/gpu/gpu.hpp>
#include <opencv2/nonfree/gpu.hpp>
#include <opencv2/nonfree/features2d.hpp> 
#include <iostream>

using namespace std;
using namespace cv;

Mat rotatedImage(const Mat & _src, double _degree)
{
	int width_src = _src.cols;
	int height_src = _src.rows;

	float center_x = width_src / 2.0;
	float center_y = height_src / 2.0;
	
	double angle =  _degree  * CV_PI / 180.; 
	double a = sin(angle), b = cos(angle);

	Mat map_matrix = getRotationMatrix2D(Point2f(center_x, center_y), _degree, 1.0);//获得旋转矩阵
	int height_rotated = height_src*fabs(b) + width_src*fabs(a);
	int width_rotated = height_src*fabs(a) + width_src*fabs(b);

	map_matrix.at<double>(0, 2) += (width_rotated - width_src) / 2.0; //将坐标移到中点
	map_matrix.at<double>(1, 2) += (height_rotated - height_src) / 2.0; //将坐标移到中点

	Mat dst;
	warpAffine(_src, dst, map_matrix, Size(width_rotated, height_rotated), 
		CV_INTER_CUBIC | CV_WARP_FILL_OUTLIERS, BORDER_CONSTANT, cvScalarAll(0));

	return dst;
}

//主要获得surf特征点、描述子、及特征点匹配
void surfExtractor(Mat& _src_Img, Mat& _dst_Img )
{
	gpu::GpuMat src_gpu(_src_Img);
	gpu::GpuMat dst_gpu(_dst_Img);

	std::vector<KeyPoint> keypoints_src;
	std::vector<KeyPoint> keypoints_dst;
	std::vector<DMatch> matches;

	gpu::SURF_GPU FeatureFinder_gpu(500);

	gpu::GpuMat keypoints_gpu_src, keypoints_gpu_dst;
	gpu::GpuMat descriptors_gpu_src, descriptors_gpu_dst;
	std::vector<float> descriptors_v1, descriptors_v2;
	//计算特征点和特征描述子
	FeatureFinder_gpu(src_gpu, gpu::GpuMat(), keypoints_gpu_src, descriptors_gpu_src);
	FeatureFinder_gpu(dst_gpu, gpu::GpuMat(), keypoints_gpu_dst, descriptors_gpu_dst);
	//将特征点下载回cpu,便于画图使用
	FeatureFinder_gpu.downloadKeypoints(keypoints_gpu_src, keypoints_src);
	FeatureFinder_gpu.downloadKeypoints(keypoints_gpu_dst, keypoints_dst);
	//使用gpu提供的BruteForceMatcher进行特征点匹配
	gpu::BruteForceMatcher_GPU< L2<float> > matcher_lk;
	matcher_lk.match(descriptors_gpu_src, descriptors_gpu_dst, matches, gpu::GpuMat());

	float max_distance = 0.2; 	//定义特征点好坏衡量距离
	std::vector<DMatch> good_matches;  //收集较好的匹配点

	for (int i = 0; i < descriptors_gpu_src.rows; i++) {
		if (matches[i].distance < max_distance) {
			good_matches.push_back(matches[i]);
		}
	}

	Mat image_matches;
	drawMatches(_src_Img, keypoints_src, _dst_Img, keypoints_dst, good_matches,
		image_matches, Scalar(0, 255, 0) , Scalar::all(-1), vector<char>(), 0);
	 
	imshow("Gpu Surf", image_matches);

}

void orbExtractor(Mat& _src_Img, Mat& _dst_Img)
{
	gpu::GpuMat src_gpu(_src_Img);
	gpu::GpuMat dst_gpu(_dst_Img);

	std::vector<KeyPoint> keypoints_src, keypoints_dst;
	gpu::GpuMat descriptors_gpu_src, descriptors_gpu_dst;
	std::vector<DMatch> matches;

	gpu::ORB_GPU orb_finder(500);
	orb_finder.blurForDescriptor = true;   //设置模糊

	cv::gpu::GpuMat fullmask_1(src_gpu.size(), CV_8U, 0xFF);
	cv::gpu::GpuMat fullmask_2(dst_gpu.size(), CV_8U, 0xFF);

	orb_finder(src_gpu, fullmask_1, keypoints_src, descriptors_gpu_src);
	orb_finder(dst_gpu, fullmask_2, keypoints_dst, descriptors_gpu_dst);

	//使用gpu提供的BruteForceMatcher进行特征点匹配
	gpu::BruteForceMatcher_GPU< HammingLUT > matcher_lk;
	matcher_lk.match(descriptors_gpu_src, descriptors_gpu_dst, matches, gpu::GpuMat());

	float max_distance = 60; 	//定义特征点好坏衡量距离
	std::vector<DMatch> good_matches;  //收集较好的匹配点

	for (int i = 0; i < descriptors_gpu_src.rows; i++) {
		if (matches[i].distance < max_distance) {
			good_matches.push_back(matches[i]);
		}
	}

	Mat image_matches;
	drawMatches(_src_Img, keypoints_src, _dst_Img, keypoints_dst, good_matches,
		image_matches, Scalar(255, 0, 0), Scalar::all(-1), vector<char>(), 0);

	imshow("Gpu ORB", image_matches);

}


int main()
{
	int num_devices = cv::gpu::getCudaEnabledDeviceCount();
	if (num_devices <= 0)
	{
		std::cerr << "There is no device." << std::endl;
		return -1;
	}
	int enable_device_id = -1;
	for (int i = 0; i < num_devices; i++)
	{
		cv::gpu::DeviceInfo dev_info(i);
		if (dev_info.isCompatible())
		{
			enable_device_id = i;
		}
	}
	if (enable_device_id < 0)
	{
		std::cerr << "GPU module isn't built for GPU" << std::endl;
		return -1;
	}
	gpu::setDevice(enable_device_id);

	Mat src_Img = imread("book.bmp" , 0);
	Mat dst_Img = rotatedImage(src_Img, -30.0);

	surfExtractor(src_Img, dst_Img);
	orbExtractor(src_Img, dst_Img);

	cv::waitKey(0);
	return 0;  
}

三、运行结果

运行环境为vs2013+opencv2.4.9+cuda7.0,结果展示如下,orb算法寻找特征点及计算描述子速度较快,gpu版的surf特征点对输入图片大小有要求,不能太小







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

opencv上gpu版surf特征点与orb特征点提取及匹配实例 的相关文章

  • 为什么块的大小不能设置太小,也不能设置太大?

    xff08 1 xff09 HDFS的块设置太小 xff0c 会增加寻址时间 xff0c 程序一直在找块的开始位置 xff1b xff08 2 xff09 如果块设置的太大 xff0c 从磁盘传输数据的时间会明显大于定位这个块开始位置所需的
  • 深入理解混洗过程

    混洗过程 Map方法之后 xff0c Reduce方法之前的数据处理过程称之为Shuffle 混洗过程 map方法之后 首先进入getpartition方法 标记数据属于那个分区 并打上分区编号 因为后续的数据都是按分区处理 不同分区数据会
  • 大数据集群写数据流程原理分析

    写入数据流程 即客户端如何把数据写入hdfs集群 底层原理如下 右侧为hdfs集群 含有NameNode和DataNode节点 左侧为客户端准备把数据传送到集群 首先创建客户端 分布式的文件系统 创建好客户端后向NameNode请求 Nam
  • 集群资源管理基础架构和工作机制

    Yarn的基础架构 RM为整个yarn集群资源老大 NM为单个节点资源老大 AM为单个应用程序的资源老大 container容器 xff0c 集群的资源抽象 最小单位 xff1b Yarn工作机制 Job gt RM 在命令行上执行一个wc
  • OpenSSL 3.0 版本已经发布VS2019编译源码教程

    1 OpenSSL 3 0版本在2020年五月发布 OpenSSL3 0 在2020年5月发布了第一个版本 xff0c 随即在六月份又发布了一些alpha版本 xff0c 版本修正了一些bug xff0c 增加了一些协议支持 xff0c 继
  • FFmpeg 4.3 源码在windows上的编译

    FFmpeg开发环境准备 nbsp nbsp 学习目标 nbsp nbsp nbsp 学会配置vs2019 msys2 编译环境 nbsp nbsp nbsp 学会编译x264 x265 fdk aac sdl ffmpeg4 3 编译目的
  • cmake使用方法详解 - Windows Linux MacOS cmake安装教程

    一 什么是CMake xff0c 为什么要使用它 CMake 是用于构建 测试和软件打包的开源跨平台工具 xff0c 为什么要用cmake xff0c 是因为我们需要一个构建系统解决如下问题 xff1a 1 你想避免硬编码路径 2 您需要在
  • cmake是什么,为什么现在都用cmake,cmake编译原理和跨平台示例

    一 cmake是什么 xff1f CMake是一个开源 跨平台的工具系列 xff0c 是用来构建 测试和打包软件 CMake使用平台无关的配置文件来控制软件编译过程 xff0c 并生成可在您选择的编译器环境中使用项目文件 xff0c 比如可
  • Socket通信原理

    对TCP IP UDP Socket编程这些词你不会很陌生吧 xff1f 随着网络技术的发展 xff0c 这些词充斥着我们的耳朵 那么我想问 xff1a 1 什么是TCP IP UDP xff1f 2 Socket在哪里呢 xff1f 3
  • cmake add_library编译链接静态库cmakelists

    本篇文章我们来编写CMakeLists txt使用cmake的add library的构建静态库 xff0c 并使用target link libraries链接指定的静态库 cmake的linux windows 和linux环境的准备可
  • FFmpeg3最新的解码接口avcodec_send_packet和avcodec_receive_frame分析

    ffmpeg3版本的解码接口做了不少调整 xff0c 之前的视频解码接口avcodec decode video2和avcodec decode audio4音频解码被设置为deprecated xff0c 对这两个接口做了合并 xff0c
  • ffmpeg3.3新版本AVStream的封装流参数由codec替换codecpar(解码)

    ffmpeg新版本中 xff08 封装流 xff09 AVStream的codec参数要被codecpar参数所替代 xff0c 这样替代我们要注意什么 xff0c 为什么要替代 xff0c 我们先来看下ffmpeg的代码 代码分析和新参数
  • 为什么 qt 成为 c++ 界面编程的第一选择?

    为什么qt成为c 43 43 界面编程的第一选择 一 前言 为什么现在QT越来越成为界面编程的第一选择 xff0c 笔者从事qt界面编程已经有接近8年 xff0c 在这之前我做C 43 43 界面都是基于MFC xff0c 也做过5年左右
  • C++QT5跨平台界面编程原理和实战大全-夏曹俊-专题视频课程

    C 43 43 QT5跨平台界面编程原理和实战大全 4271人已学习 课程介绍 课程讲解基于QT5 9 SDK xff0c 包含QT界面编程的核心内容 xff0c 并提供全部源码 xff0c 课程讲解方式是接口讲解 分析 演示示例 xff0
  • Darknet问题:ERROR: Cannot load message class for [darknet_ros_msgs/BoundingBoxes].

    运行darknet ros进行目标检测时 xff0c 通过 rostopic list查看到 darknet ros bounding boxes这个话题 xff0c 因此想查看该话题的数据 xff0c 在使用 rostopic echo
  • ROS问题:ERROR: cannot launch node of type

    在运行launch文件时 xff0c 出现如下错误提示 xff1a 原因是没有source 所以解决方案就是在编译完成之后添加source devel setup bash xff0c 问题解决 参考网址 xff1a ERROR canno
  • 标注工具labelme的使用

    在做目标检测任务时 xff0c 少不了对图像进行标注 xff0c 标注工具有好几种 xff0c labelme是其中比较好用的一种 labelme可对图像进行标注 xff0c 包括多边形 矩形 线 点和图像级标注 它是用Python编写的
  • Linux小技巧之终端terminal全选

    当打开一个终端 xff0c 经过若干指令后 xff0c 终端上输出的内容较多 xff0c 直接框选这些内容进行选择比较费事 有没有全选的功能呢 xff1f 答案是有的 xff01 方法1 xff1a 终端菜单栏全选 当窗口比较小时 xff0
  • 如何使用set::key_comp 和 set::value_comp 标准模板库 (STL) 函数

    下面的代码示例演示如何使用 Visual C 43 43 set key comp 和 set value comp 的 STL 功能 所需要的头文件 xff1a lt set gt 原型 template lt class K class
  • Linux小技巧之终端快捷键大全

    在前面一篇博客中记录了终端全选的技巧 下面记录一下关于终端使用的其它一些小技巧 F1查看帮助F11全屏Shift 43 Ctrl 43 T 打开一个新的终端Shift 43 Ctrl 43 N新建一个窗口打开终端Shift 43 Ctrl

随机推荐

  • ROS问题:Yolo v4移植到ROS后检测结果/darknet_ros/detection_image在rviz中显示乱码

    在前面一篇博客 xff08 Yolo v4移植ROS xff09 中介绍了将Yolo v4移植到ROS中 由于Yolo v4的源码在Yolo v3源码的基础上有改动 xff0c 移植成功后会出现一个小bug xff0c 如下图所示 xff1
  • 吉洪诺夫正则化(Tikhonov regularization )

    最近看了看吉洪诺夫正则化方法 xff0c 对其基本内容作了一个简单的了解 现在总结如下 1 正则化 定义 xff1a 正则化 regularization xff0c 是指在线性代数理论中 xff0c 不适定问题通常是由一组线性代数方程定义
  • C++中getline()、gets()等函数的用法

    在学习C 43 43 的过程中 xff0c 经常会遇到输入输出的问题 xff0c 以下总结一下下面几个函数的用法 xff1a 1 cin 2 cin get 3 cin getline 4 getline 5 gets 1 cin gt g
  • C++字母大小写转换方法

    字母大小写这个问题相对比较简单 xff0c 总结了一些常用的大小写转换的方法 xff0c 欢迎指正补充 xff01 思路1 xff1a 根据字母的ASCII表进行转换 xff1a 由表格可以看出 xff0c 对应大小写字母之间相差32 xf
  • C++ 标准输出控制小数点后位数的方法

    在C 43 43 中 xff0c 要实现这个功能 xff0c 就要用到std命名空间中常用于流的控制符 xff0c 这里通常要用到setprecision 函数 xff0c 可以通过这个函数控制小数点后面位数 还要注意的是 xff0c 使用
  • C++中string::npos的一些用法总结

    一 关于npos的定义 在MSDN中有如下说明 xff1a basic string npos static const size type npos 61 1 定义 The constant is the largest represen
  • CMake:通过target_link_libraries链接第三方库

    sdbusplus 通过new method call同步调用service的method 风静如云的博客 CSDN博客 例子中需要在编译时链接 lsdbusplus lsystemd 这两个第三方库 那么通过cmake怎么指定呢 其实很简
  • 在ubuntu终端打开谷歌浏览器的命令

    安装好谷歌浏览器后 xff0c 用以下命令在终端打开谷歌浏览器 adb shell am start n com android chrome com google android apps chrome Main 之后便出现如下内容 xf
  • PELCO_D通信协议

    1 球机通信接口 xff08 EIA RS 485 xff09 数据传输方式 xff1a 异步半双工串行通讯 通信波特率 xff1a 9600Bps 数据格式 xff1a Start Bit xff1a 1 Bit xff1b Data B
  • C buffer

    这学期在Dartmouth上ENGS20 Introduction to Scientific Computing xff0c 好多东西不记下来就会忘 xff0c 所以开一个笔记 在C语言中 xff0c 输入和输出都是有buffer的 xf
  • 寄存器值的操作方法

    通过这段时间的工作和学习 xff0c 我感觉在嵌入式硬件编程中 xff0c 大多数情况下都是对相应硬件的功能寄存器进行设置和操作 一 寄存器的设置和操作特性 1 xff0c 一个寄存器的每个位有其不同的意义 xff0c 进行不同的设置会使硬
  • UART串口通信(回环测试)

    一 UART串口通信简介 UART xff08 Universal Asynchronous Receiver Transmitter xff09 是采用异步串行通信方式的通用异步收发传输器 xff0c 在发送数据时将并行数据转换为串行数据
  • extern "C"的作用

    extern 34 C 34 的作用 一 前些天 编程序是用到了很久以前写的C程序 想把里面的函数利用起来 连接发现出现了找不到具体函数的错误 以下是假设旧的C程序库 C的头文件 c h ifndef C H define C H exte
  • 输入分钟数,按小时和分钟输出

    copyright C 2014 2015 Lighting Studio Co Ltd File name xff1a Author xff1a Jerey Jobs Version 0 1 Date Description xff1a
  • 输入一个32位的整数a,使用按位异或^运算,生成一个新的32位整数b,使得该整数b的每一位等于原整数a中该位左右两边两个bit位的异或结果

    程序要求 xff1a 输入一个32位的整数a 使用按位异或 运算 生成一个新的32位整数b 使得该整数b的每一位等于原整数a中该位左右两边两个bit位的异或结果 copyright C 2014 2015 Lighting Studio C
  • sqlite回调函数的解释与使用

    gt 在sqlite3的api函数中有一个sqlite3 exec xff0c 用来执行sql语句 xff1a 函数原型 xff1a int sqlite3 exec sqlite3 ppDb An open database const
  • Linux节点理解

    一 inode是什么 xff1f 理解inode xff0c 要从文件储存说起 文件储存在硬盘上 xff0c 硬盘的最小存储单位叫做 扇区 xff08 Sector xff09 每个扇区储存512字节 xff08 相当于0 5KB xff0
  • OSSempend();OSSemPost();函数的解析

    浅析 COS II v2 span class hljs number 85 span 内核OSSemPend 和OSSemPost 函数工作原理 文章来源 http span class hljs comment gliethttp cu
  • 矩阵键盘时钟

    span class hljs preprocessor include lt reg52 h gt span class hljs comment 包含头文件 xff0c 一般情况不需要改动 xff0c 头文件包含特殊功能寄存器的定义 s
  • opencv上gpu版surf特征点与orb特征点提取及匹配实例

    一 前言 本文主要实现了使用opencv里的gpu版surf特征检测器和gpu版orb检测器 xff0c 分别对图片进行特征点提取及匹配 xff0c 并对寻获的特征点进行了距离筛选 xff0c 将匹配较为好的特征点进行展示 二 实现代码 我