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

一、前言

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

二、实现代码

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

  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特征点对输入图片大小有要求,不能太小

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

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