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

标签: gpu版surfgpu orbsurf和orbgpu surf及orbsurf orb gpu
2016-09-25 23:42 464人阅读 评论(0) 收藏 举报
 分类:
opencv(13) 

版权声明:本文为博主原创文章,未经博主允许不得转载。

一、前言

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

二、实现代码

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

[cpp] view plaincopy print?
  1. //main.cpp//
  2. #include <opencv2/core/core.hpp>
  3. #include <opencv2/imgproc/imgproc.hpp>
  4. #include <opencv2/highgui/highgui.hpp>
  5. #include <opencv2/gpu/gpu.hpp>
  6. #include <opencv2/nonfree/gpu.hpp>
  7. #include <opencv2/nonfree/features2d.hpp>
  8. #include <iostream>
  9. using namespace std;
  10. using namespace cv;
  11. Mat rotatedImage(const Mat & _src, double _degree)
  12. {
  13. int width_src = _src.cols;
  14. int height_src = _src.rows;
  15. float center_x = width_src / 2.0;
  16. float center_y = height_src / 2.0;
  17. double angle =  _degree  * CV_PI / 180.;
  18. double a = sin(angle), b = cos(angle);
  19. Mat map_matrix = getRotationMatrix2D(Point2f(center_x, center_y), _degree, 1.0);//获得旋转矩阵
  20. int height_rotated = height_src*fabs(b) + width_src*fabs(a);
  21. int width_rotated = height_src*fabs(a) + width_src*fabs(b);
  22. map_matrix.at<double>(0, 2) += (width_rotated - width_src) / 2.0; //将坐标移到中点
  23. map_matrix.at<double>(1, 2) += (height_rotated - height_src) / 2.0; //将坐标移到中点
  24. Mat dst;
  25. warpAffine(_src, dst, map_matrix, Size(width_rotated, height_rotated),
  26. CV_INTER_CUBIC | CV_WARP_FILL_OUTLIERS, BORDER_CONSTANT, cvScalarAll(0));
  27. return dst;
  28. }
  29. //主要获得surf特征点、描述子、及特征点匹配
  30. void surfExtractor(Mat& _src_Img, Mat& _dst_Img )
  31. {
  32. gpu::GpuMat src_gpu(_src_Img);
  33. gpu::GpuMat dst_gpu(_dst_Img);
  34. std::vector<KeyPoint> keypoints_src;
  35. std::vector<KeyPoint> keypoints_dst;
  36. std::vector<DMatch> matches;
  37. gpu::SURF_GPU FeatureFinder_gpu(500);
  38. gpu::GpuMat keypoints_gpu_src, keypoints_gpu_dst;
  39. gpu::GpuMat descriptors_gpu_src, descriptors_gpu_dst;
  40. std::vector<float> descriptors_v1, descriptors_v2;
  41. //计算特征点和特征描述子
  42. FeatureFinder_gpu(src_gpu, gpu::GpuMat(), keypoints_gpu_src, descriptors_gpu_src);
  43. FeatureFinder_gpu(dst_gpu, gpu::GpuMat(), keypoints_gpu_dst, descriptors_gpu_dst);
  44. //将特征点下载回cpu,便于画图使用
  45. FeatureFinder_gpu.downloadKeypoints(keypoints_gpu_src, keypoints_src);
  46. FeatureFinder_gpu.downloadKeypoints(keypoints_gpu_dst, keypoints_dst);
  47. //使用gpu提供的BruteForceMatcher进行特征点匹配
  48. gpu::BruteForceMatcher_GPU< L2<float> > matcher_lk;
  49. matcher_lk.match(descriptors_gpu_src, descriptors_gpu_dst, matches, gpu::GpuMat());
  50. float max_distance = 0.2;   //定义特征点好坏衡量距离
  51. std::vector<DMatch> good_matches;  //收集较好的匹配点
  52. for (int i = 0; i < descriptors_gpu_src.rows; i++) {
  53. if (matches[i].distance < max_distance) {
  54. good_matches.push_back(matches[i]);
  55. }
  56. }
  57. Mat image_matches;
  58. drawMatches(_src_Img, keypoints_src, _dst_Img, keypoints_dst, good_matches,
  59. image_matches, Scalar(0, 255, 0) , Scalar::all(-1), vector<char>(), 0);
  60. imshow("Gpu Surf", image_matches);
  61. }
  62. void orbExtractor(Mat& _src_Img, Mat& _dst_Img)
  63. {
  64. gpu::GpuMat src_gpu(_src_Img);
  65. gpu::GpuMat dst_gpu(_dst_Img);
  66. std::vector<KeyPoint> keypoints_src, keypoints_dst;
  67. gpu::GpuMat descriptors_gpu_src, descriptors_gpu_dst;
  68. std::vector<DMatch> matches;
  69. gpu::ORB_GPU orb_finder(500);
  70. orb_finder.blurForDescriptor = true;   //设置模糊
  71. cv::gpu::GpuMat fullmask_1(src_gpu.size(), CV_8U, 0xFF);
  72. cv::gpu::GpuMat fullmask_2(dst_gpu.size(), CV_8U, 0xFF);
  73. orb_finder(src_gpu, fullmask_1, keypoints_src, descriptors_gpu_src);
  74. orb_finder(dst_gpu, fullmask_2, keypoints_dst, descriptors_gpu_dst);
  75. //使用gpu提供的BruteForceMatcher进行特征点匹配
  76. gpu::BruteForceMatcher_GPU< HammingLUT > matcher_lk;
  77. matcher_lk.match(descriptors_gpu_src, descriptors_gpu_dst, matches, gpu::GpuMat());
  78. float max_distance = 60;    //定义特征点好坏衡量距离
  79. std::vector<DMatch> good_matches;  //收集较好的匹配点
  80. for (int i = 0; i < descriptors_gpu_src.rows; i++) {
  81. if (matches[i].distance < max_distance) {
  82. good_matches.push_back(matches[i]);
  83. }
  84. }
  85. Mat image_matches;
  86. drawMatches(_src_Img, keypoints_src, _dst_Img, keypoints_dst, good_matches,
  87. image_matches, Scalar(255, 0, 0), Scalar::all(-1), vector<char>(), 0);
  88. imshow("Gpu ORB", image_matches);
  89. }
  90. int main()
  91. {
  92. int num_devices = cv::gpu::getCudaEnabledDeviceCount();
  93. if (num_devices <= 0)
  94. {
  95. std::cerr << "There is no device." << std::endl;
  96. return -1;
  97. }
  98. int enable_device_id = -1;
  99. for (int i = 0; i < num_devices; i++)
  100. {
  101. cv::gpu::DeviceInfo dev_info(i);
  102. if (dev_info.isCompatible())
  103. {
  104. enable_device_id = i;
  105. }
  106. }
  107. if (enable_device_id < 0)
  108. {
  109. std::cerr << "GPU module isn't built for GPU" << std::endl;
  110. return -1;
  111. }
  112. gpu::setDevice(enable_device_id);
  113. Mat src_Img = imread("book.bmp" , 0);
  114. Mat dst_Img = rotatedImage(src_Img, -30.0);
  115. surfExtractor(src_Img, dst_Img);
  116. orbExtractor(src_Img, dst_Img);
  117. cv::waitKey(0);
  118. return 0;
  119. }

三、运行结果

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

使用GPU提取SURF局部特征

GPU做SURF特征提取的接口和CPU版本有所不同,不过这一部分可以完全参考<opencv_source_directory>/samples/gpu/surf_keypoint_matcher.cpp的例子代码。 
我这里给出一个更加简化的例子,并添加一些中文注释和说明。

/*surf.cpp*/                                                                                                                                             #include <opencv2/imgcodecs.hpp>
#include <opencv2/xfeatures2d/cuda.hpp>
#include <opencv2/cudafeatures2d.hpp>using namespace std;int GetMatchPointCount(const char * pic_path_1,const char * pic_path_2) {/*指定使用的GPU序号,相关的还有下面几个函数可以使用cv::cuda::getCudaEnabledDeviceCount();cv::cuda::getDevice();cv::cuda::DeviceInfo*/cv::cuda::setDevice(0);/*向显存加载两张图片。这里需要注意两个问题:第一,我们不能像操作(主)内存一样直接一个字节一个字节的操作显存,也不能直接从外存把图片加载到显存,一般需要通过内存作为媒介第二,目前opencv的GPU SURF仅支持8位单通道图像,所以加上参数IMREAD_GRAYSCALE*/cv::cuda::GpuMat gmat1;cv::cuda::GpuMat gmat2;gmat1.upload(cv::imread(pic_path_1,cv::IMREAD_GRAYSCALE));gmat2.upload(cv::imread(pic_path_2,cv::IMREAD_GRAYSCALE));/*下面这个函数的原型是:explicit SURF_CUDA(double _hessianThreshold, //SURF海森特征点阈值int _nOctaves=4, //尺度金字塔个数int _nOctaveLayers=2, //每一个尺度金字塔层数bool _extended=false, //如果true那么得到的描述子是128维,否则是64维float _keypointsRatio=0.01f, bool _upright = false );要理解这几个参数涉及SURF的原理*/cv::cuda::SURF_CUDA surf(100,4,3);  /*分配下面几个GpuMat存储keypoint和相应的descriptor*/cv::cuda::GpuMat keypt1,keypt2;cv::cuda::GpuMat desc1,desc2;/*检测特征点*/surf(gmat1,cv::cuda::GpuMat(),keypt1,desc1);surf(gmat2,cv::cuda::GpuMat(),keypt2,desc2);/*匹配,下面的匹配部分和CPU的match没有太多区别,这里新建一个Brute-Force Matcher,一对descriptor的L2距离小于0.1则认为匹配*/auto matcher=cv::cuda::DescriptorMatcher::createBFMatcher(cv::NORM_L2);vector<cv::DMatch> match_vec;matcher->match(desc1,desc2,match_vec);int count=0;for(auto & d:match_vec){if(d.distance<0.1) count++;}return count;
}int main(int argc, const char* argv[])
{GetMatchPointCount(argv[1],argv[2]);return 0;
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

最后,编译这个例子,可以参考下面通用的编译命令:

g++ -std=c++11 surf.cpp `pkg-config --cflags opencv` `pkg-config --libs opencv`
  • 1
  • 1

更简化的编译命令:

g++ -std=c++11 surf.cpp -lopencv_xfeatures2d -lopencv_cudafeatures2d

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

  1. 视觉里程计:特征点法之ORB特征点

    VO的核心问题在于根据图像信息估计相机的运动轨迹 .通常从图像中选取具有代表性的点,并当相机运动后,从不同的图像中找到对应的相同点,从而确定相机位姿估计问题.在经典SLAM模型中,称这种点为路标,而在 ...

  2. OpenCV中GPU版MOG2的使用

    最近项目中的GMM算法,需要改成GPU版,以降低CPU占用.重新编译了opencv2.4.13,网上很多教程,不再赘述.说一下自己遇到的坑.项目用caffee,cuda版本8.0,opencv2.4. ...

  3. opencv检测相交点_OpenCV特征点检测------ORB特征

    ORB是是ORiented Brief的简称.ORB的描述在下面文章中: Ethan Rublee and Vincent Rabaud and Kurt Konolige and Gary Brad ...

  4. 【特征描述】ORB详解(附python实例代码)

    文章目录 特征描述 ORB ORB特征描述 ORB的基本思路 FAST角点检测的缺点 BRIEF的缺点 BRIEF ORB对BRIEF的改进 完整代码如下 特征描述 ORB ORB 算法创建的特征向量 ...

  5. 图像拼接(二):柱面投影+模板匹配+渐入渐出融合(GPU版)

    本篇博客的代码修改自图像拼接(一):柱面投影+模板匹配+渐入渐出融合.新的代码充分利用了OpenCV库函数的GPU版本.在一些方法中使用了GpuMat这一数据结构,它是Mat的替代.Mat运行在CPU ...

  6. opencv的GPU编程(一)

    最近在做人脸检测的速度优化工作,对OPENCV下利用GPU加速人脸检测做了一些了解,现对齐进行梳理,了解下大概,主要内容来自 OPENCV tutorial on GPU 首先,是关于OPENCV上G ...

  7. opencv中的SIFT,SURF,ORB,FAST 特征描叙算子比较

    opencv中的SIFT,SURF,ORB,FAST 特征描叙算子比较 参考: http://wenku.baidu.com/link?url=1aDYAJBCrrK-uk2w3sSNai7h52x_ ...

  8. (转)在Windows上安装GPU版Tensorflow

    转载自在Windows上安装GPU版Tensorflow. 1. 下载安装Anaconda 简单说就是下载 64位 python 3.5 版本的Anaconda https://www.continu ...

  9. 在windows11上安装cuda,cudnn,以及GPU版的pytorch

    第一步:查看自己电脑的配置,是否是GPU型的电脑 方法1:快捷键方式 Ctrl+Shift+Esc键-->性能(或Windows键+X-->任务管理器-->性能),如果有GPU就说明 ...

最新文章

  1. Coolite 中GridView点击行中的按钮时跳转至不同的页面
  2. php 仓储 sqlite_详解php封装db类连接sqlite3
  3. Sentinel集群流控
  4. linux用分词系统,Linux(CentOS 6.4)Solr4.8.1中文分词配置(IK分词)
  5. python能做什么工作-python语言能做什么工作
  6. html 段前空格_前端 -- HTML
  7. UIWebView关于XMLHttpRequest的内存泄漏
  8. CentOS6.7系统优化加强牢固脚本
  9. xml mysql 树形数据删除_使用递归删除树形结构的所有子节点(java和mysql实现)
  10. mysql自定义函数for循环_mysql自定义函数
  11. python算法精解pdf_算法详解(卷1)算法基础 PDF 完整高清版
  12. python用于pmc排产可以吗_有没有免费的PMC生产排程软件啊?
  13. 测绘——利用ExifTool提取照片exif信息【windows环境下】(信息非常全)
  14. win10下载ie浏览器
  15. FPGA_UART串口通信
  16. 解决-PPT文件不能编辑问题
  17. 阿里妈妈不能攻百度也不能守淘宝 !
  18. SpringBoot实现12306自动抢票系统
  19. 3dsmaxC4DbodypainterPS画贴图一、展开模型UV。
  20. BUUCTF:[SWPU2019]Network

热门文章

  1. python 打包egg_将Python程序打包到egg或WHL安装包或exe包中,把,python,成,或者,whl
  2. jboss1.7_在JBoss Fuse / Fabric8 / Karaf中使用Byteman
  3. 数据结构乐智教学百度云_网易云课堂 - 我的职业课堂
  4. linux的内核设计,Linux内核设计艺术(经典).pdf
  5. Homebrew安装不要改hosts了,直接用这个国内源才爽!
  6. 收下这个“短信验证”的最佳实践项目!
  7. 这款 网络排查 神器,运维用了都说好,赶紧收藏~
  8. 如何自己搞一个维基百科?
  9. 皮一皮:中国好邻居!
  10. 皮一皮:据说这样去拜佛比较灵...