当前位置:   article > 正文

【opencv】教程代码 —features2D(2)

【opencv】教程代码 —features2D(2)

使用SURF算法检测两幅图关键点后暴力匹配

SURF特征检测

使用SURF(Speeded Up Robust Features)算法来检测两张图像之间的关键点,并使用FLANN(Fast Library for Approximate Nearest Neighbors)基于特征描述符向量进行匹配

图像特征点检测(SURF)、(FLANN)匹配和目标定位

1.feature_description—SURF_matching_Demo.cpp(Debug模式)使用SURF算法检测两幅图关键点后暴力匹配

5d2215a509e099110a897b45e4bcd0a7.png

box.png

9f32be968bf98412e06bc71f3decfee6.png

box_in_scene.png

708d7dfeccbd55a5a67018744f85c2be.png

minHessian=400

1aa3e6c00029a382a651dfb8fde6ed23.png

minHessian=1000

6128a411d9dad7c93dc1218bdddb225f.png

minHessian=10000

911da9be70835cf10d8a2c2ca2e25c1a.png

  1. #include <iostream> // 包含标准输入输出流库
  2. #include "opencv2/core.hpp" // 包括OpenCV的核心功能头文件
  3. #ifdef HAVE_OPENCV_XFEATURES2D // 如果定义了HAVE_OPENCV_XFEATURES2D
  4. #include "opencv2/highgui.hpp" // 包括用户界面相关功能的头文件
  5. #include "opencv2/features2d.hpp" // 包括特征检测相关功能的头文件
  6. #include "opencv2/xfeatures2d.hpp" // 包括特殊特征检测的头文件(非free模块)
  7. using namespace cv; // 使用cv命名空间
  8. using namespace cv::xfeatures2d; // 使用cv的xfeatures2d命名空间
  9. using std::cout; // 使用标准库中的cout
  10. using std::endl; // 使用标准库中的endl
  11. const char* keys = // 定义命令行参数
  12. "{ help h | | Print help message. }"
  13. "{ input1 | box.png | Path to input image 1. }"
  14. "{ input2 | box_in_scene.png | Path to input image 2. }";
  15. int main( int argc, char* argv[] ) // 主函数
  16. {
  17. CommandLineParser parser( argc, argv, keys ); // 创建命令行解析器
  18. Mat img1 = imread( samples::findFile( parser.get<String>("input1") ), IMREAD_GRAYSCALE ); // 读取第一张图片为灰度图
  19. Mat img2 = imread( samples::findFile( parser.get<String>("input2") ), IMREAD_GRAYSCALE ); // 读取第二张图片为灰度图
  20. if ( img1.empty() || img2.empty() ) // 如果图片读取失败
  21. {
  22. cout << "Could not open or find the image!\n" << endl; // 打印错误信息
  23. parser.printMessage(); // 打印帮助信息
  24. return -1; // 返回错误代码
  25. }
  26. //-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors
  27. int minHessian = 400; // 设置SURF算法的Hessian阈值
  28. Ptr<SURF> detector = SURF::create( minHessian ); // 创建SURF特征检测器
  29. std::vector<KeyPoint> keypoints1, keypoints2; // 存放两张图片的关键点
  30. Mat descriptors1, descriptors2; // 存放两张图片的描述符
  31. detector->detectAndCompute( img1, noArray(), keypoints1, descriptors1 ); // 检测并计算img1的关键点和描述符
  32. detector->detectAndCompute( img2, noArray(), keypoints2, descriptors2 ); // 检测并计算img2的关键点和描述符
  33. //-- Step 2: Matching descriptor vectors with a brute force matcher
  34. // Since SURF is a floating-point descriptor NORM_L2 is used
  35. Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(DescriptorMatcher::BRUTEFORCE); // 创建暴力匹配器
  36. std::vector< DMatch > matches; // 存放匹配结果
  37. matcher->match( descriptors1, descriptors2, matches ); // 执行匹配
  38. //-- Draw matches
  39. Mat img_matches; // 存放匹配之后的图片
  40. drawMatches( img1, keypoints1, img2, keypoints2, matches, img_matches ); // 绘制匹配结果
  41. //-- Show detected matches
  42. imshow("Matches", img_matches ); // 在窗口中显示匹配结果
  43. waitKey(); // 等待用户按键
  44. return 0; // 程序成功结束
  45. }
  46. #else
  47. int main() // 如果没定义HAVE_OPENCV_XFEATURES2D
  48. {
  49. std::cout << "This tutorial code needs the xfeatures2d contrib module to be run." << std::endl; // 提示需要xfeatures2d模块
  50. return 0; // 程序结束
  51. }
  52. #endif

这段代码是使用OpenCV库进行图像特征点检测和匹配的示例。它通过SURF算法来检测两幅图片中的特征点,并使用暴力匹配器来找出这些特征点之间的匹配关系。最终将匹配的结果用图形化的方式展示出来。这对于很多计算机视觉任务,比如物体识别、图像拼接等是非常实用的。如果环境中没有安装OpenCV的xfeatures2d模块,则给出提示信息。

e942b242e11c0c6c54a5fa63620bc523.png

2.feature_detection—SURF_detection_Demo.cpp  SURF特征检测

38f480fb07cd90b6c8af1c0da83425bd.png

675595e35ce838102ea85f88c84d6b7b.png

  1. #include <iostream> // 包含输入输出流的头文件
  2. #include "opencv2/core.hpp" // 包含OpenCV核心功能的头文件
  3. #ifdef HAVE_OPENCV_XFEATURES2D
  4. #include "opencv2/highgui.hpp" // 包含OpenCV GUI功能的头文件
  5. #include "opencv2/features2d.hpp" // 包含OpenCV特征检测相关功能的头文件
  6. #include "opencv2/xfeatures2d.hpp" // 包含OpenCV extra features2d模块的头文件,例如SURF
  7. using namespace cv; // 使用cv命名空间
  8. using namespace cv::xfeatures2d; // 使用cv::xfeatures2d命名空间,因为SURF是其中的一部分
  9. using std::cout; // 使用标准命名空间下的cout
  10. using std::endl; // 使用标准命名空间下的endl
  11. int main( int argc, char* argv[] )
  12. {
  13. CommandLineParser parser( argc, argv, "{@input | box.png | input image}" ); // 命令行参数解析器
  14. Mat src = imread( samples::findFile( parser.get<String>( "@input" ) ), IMREAD_GRAYSCALE ); // 读取图像文件转换为灰度图
  15. if ( src.empty() )
  16. {
  17. cout << "Could not open or find the image!\n" << endl;
  18. cout << "Usage: " << argv[0] << " <Input image>" << endl;
  19. return -1;
  20. }
  21. //-- Step 1: Detect the keypoints using SURF Detector
  22. // 步骤1:使用SURF检测器检测关键点
  23. int minHessian = 400; // Hessian算子的阈值
  24. Ptr<SURF> detector = SURF::create( minHessian ); // 创建SURF检测器
  25. std::vector<KeyPoint> keypoints; // 关键点的向量
  26. detector->detect( src, keypoints ); // 检测关键点
  27. //-- Draw keypoints
  28. // 绘制关键点
  29. Mat img_keypoints;
  30. drawKeypoints( src, keypoints, img_keypoints ); // 将检测到的关键点绘制到图上
  31. //-- Show detected (drawn) keypoints
  32. // 显示检测到(绘制的)关键点
  33. imshow("SURF Keypoints", img_keypoints ); // 创建一个窗口展示关键点
  34. waitKey(); // 等待任意键输入
  35. return 0;
  36. }
  37. #else
  38. int main()
  39. {
  40. std::cout << "This tutorial code needs the xfeatures2d contrib module to be run." << std::endl;
  41. return 0;
  42. }
  43. #endif

这段代码的功能是使用SURF算法来检测图像中的关键点。首先,它使用命令行参数解析器读取图像,并将其转换为灰度图。如果无法读取图像,它会打印错误消息并退出程序。如果图像读取成功,它创建一个SURF检测器,并根据指定的Hessian阈值来检测图像中的关键点。然后,它将这些关键点绘制在源图像上,并使用imshow函数显示结果。如果没有安装OpenCV的xfeatures2d类的附加模块,它会在命令行输出一条信息,说明需要xfeatures2d模块才能运行此代码。

3. SURF_FLANN_matching_Demo.cpp 使用SURF(Speeded Up Robust Features)算法来检测两张图像之间的关键点,并使用FLANN(Fast Library for Approximate Nearest Neighbors)基于特征描述符向量进行匹配

480c3931209ad1feb76836ec477641c5.png

0a0f8d0416a367929207b2d446b11162.png

  1. #include <iostream> // 包含标准输入输出流库
  2. #include "opencv2/core.hpp" // 包含OpenCV核心功能库
  3. #ifdef HAVE_OPENCV_XFEATURES2D // 如果定义了HAVE_OPENCV_XFEATURES2D(检查xfeatures2d模块是否可用)
  4. #include "opencv2/highgui.hpp" // 包含OpenCV高级GUI库
  5. #include "opencv2/features2d.hpp" // 包含OpenCV特征点检测库
  6. #include "opencv2/xfeatures2d.hpp" // 包含OpenCV附加特征点检测库
  7. using namespace cv; // 使用cv命名空间
  8. using namespace cv::xfeatures2d; // 使用cv::xfeatures2d命名空间
  9. using std::cout; // 使用cout(标准输出)
  10. using std::endl; // 使用endl(换行符)
  11. const char* keys = // 定义命令行参数
  12. "{ help h | | Print help message. }" // 帮助信息
  13. "{ input1 | box.png | Path to input image 1. }" // 输入图像1的路径
  14. "{ input2 | box_in_scene.png | Path to input image 2. }"; // 输入图像2的路径
  15. int main( int argc, char* argv[] ) // 主函数
  16. {
  17. CommandLineParser parser( argc, argv, keys ); // 命令行解析器
  18. Mat img1 = imread( samples::findFile( parser.get<String>("input1") ), IMREAD_GRAYSCALE ); // 读取输入图像1为灰度图
  19. Mat img2 = imread( samples::findFile( parser.get<String>("input2") ), IMREAD_GRAYSCALE ); // 读取输入图像2为灰度图
  20. if ( img1.empty() || img2.empty() ) // 如果任一图像为空则打印错误信息
  21. {
  22. cout << "Could not open or find the image!\n" << endl;
  23. parser.printMessage(); // 打印帮助信息
  24. return -1; // 返回-1表示错误
  25. }
  26. //-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors
  27. int minHessian = 400; // 定义Hessian阈值
  28. Ptr<SURF> detector = SURF::create( minHessian ); // 创建SURF检测器
  29. std::vector<KeyPoint> keypoints1, keypoints2; // 定义关键点向量
  30. Mat descriptors1, descriptors2; // 定义描述符矩阵
  31. detector->detectAndCompute( img1, noArray(), keypoints1, descriptors1 ); // 检测图像1的关键点和描述符
  32. detector->detectAndCompute( img2, noArray(), keypoints2, descriptors2 ); // 检测图像2的关键点和描述符
  33. //-- Step 2: Matching descriptor vectors with a FLANN based matcher
  34. // Since SURF is a floating-point descriptor NORM_L2 is used
  35. Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(DescriptorMatcher::FLANNBASED); // 创建基于FLANN的描述符匹配器
  36. std::vector< std::vector<DMatch> > knn_matches; // 定义K邻近匹配向量
  37. matcher->knnMatch( descriptors1, descriptors2, knn_matches, 2 ); // 执行K邻近匹配
  38. //-- Filter matches using the Lowe's ratio test
  39. const float ratio_thresh = 0.7f; // 定义Lowe's比率测试阈值
  40. std::vector<DMatch> good_matches; // 定义良好匹配向量
  41. for (size_t i = 0; i < knn_matches.size(); i++) // 遍历所有K邻近匹配
  42. {
  43. if (knn_matches[i][0].distance < ratio_thresh * knn_matches[i][1].distance) // 如果满足Lowe's比率测试则认为是良好匹配
  44. {
  45. good_matches.push_back(knn_matches[i][0]); // 添加到良好匹配向量中
  46. }
  47. }
  48. //-- Draw matches
  49. Mat img_matches; // 定义匹配结果图像
  50. drawMatches( img1, keypoints1, img2, keypoints2, good_matches, img_matches, Scalar::all(-1),
  51. Scalar::all(-1), std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ); // 绘制良好匹配
  52. //-- Show detected matches
  53. imshow("Good Matches", img_matches ); // 显示匹配结果图像
  54. waitKey(); // 等待按键事件
  55. return 0; // 返回0表示成功
  56. }
  57. #else // 如果没有定义HAVE_OPENCV_XFEATURES2D
  58. int main() // 主函数
  59. {
  60. std::cout << "This tutorial code needs the xfeatures2d contrib module to be run." << std::endl; // 打印错误信息
  61. return 0; // 返回0表示成功
  62. }
  63. #endif

这段代码是一个使用OpenCV库进行图像处理的例子,特别是使用SURF(Speeded Up Robust Features)算法来检测两张图像之间的关键点,并使用FLANN(Fast Library for Approximate Nearest Neighbors)基于特征描述符向量进行匹配。首先,代码读取两张图像并将它们转换成灰度图。然后,SURF算法被用于检测关键点并计算描述符。接着,运用FLANN匹配器对这两组描述符进行匹配,并使用Lowe's比率测试过滤出良好的匹配点。最后,良好的匹配点被绘制并显示出来。如果没有安装OpenCV的xfeatures2d模块,代码将打印一条错误信息。

  1. drawMatches( img1, keypoints1, img2, keypoints2, good_matches, img_matches, Scalar::all(-1),
  2. Scalar::all(-1), std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

b92e36a6a9d798c224c32e1b961df1b8.png

4.SURF_FLANN_matching_homography_Demo.cpp  图像特征点检测、匹配和目标定

c98a4988f0e8f4f163e525aeab49f4ff.png

8e6ebca54694c0c80c69eb93adc6ffb6.png

  1. // 引用必要的库
  2. #include <iostream>
  3. #include "opencv2/core.hpp"
  4. #ifdef HAVE_OPENCV_XFEATURES2D // 判断是否有xfeatures2d模块,如果有则进行下面的操作
  5. #include "opencv2/calib3d.hpp"
  6. #include "opencv2/highgui.hpp"
  7. #include "opencv2/imgproc.hpp"
  8. #include "opencv2/features2d.hpp"
  9. #include "opencv2/xfeatures2d.hpp"
  10. // 使用命名空间简化代码
  11. using namespace cv;
  12. using namespace cv::xfeatures2d;
  13. using std::cout;
  14. using std::endl;
  15. // 定义程序参数
  16. const char* keys =
  17. "{ help h | | 打印帮助信息}"
  18. "{ input1 | box.png | 第一张输入图像路径}"
  19. "{ input2 | box_in_scene.png | 第二张输入图像路径}";
  20. // 程序主函数
  21. int main( int argc, char* argv[] )
  22. {
  23. // 定义命令行解析器
  24. CommandLineParser parser( argc, argv, keys );
  25. // 读取图片
  26. Mat img_object = imread( samples::findFile( parser.get<String>("input1") ), IMREAD_GRAYSCALE );
  27. Mat img_scene = imread( samples::findFile( parser.get<String>("input2") ), IMREAD_GRAYSCALE );
  28. // 判断图片是否读取成功
  29. if ( img_object.empty() || img_scene.empty() )
  30. {
  31. cout << "无法打开或找到图片!\n" << endl;
  32. parser.printMessage(); //打印错误信息
  33. return -1;
  34. }
  35. //-- Step 1: 使用SURF检测器检测关键点并计算描述符
  36. int minHessian = 400; //设置SURF算法中的hessian阈值
  37. Ptr<SURF> detector = SURF::create( minHessian ); // 创建SURF检测器
  38. std::vector<KeyPoint> keypoints_object, keypoints_scene; // 定义储存关键点的向量
  39. Mat descriptors_object, descriptors_scene; //定义储存描述符的矩阵
  40. detector->detectAndCompute( img_object, noArray(), keypoints_object, descriptors_object ); // 在目标图片中检测关键点并计算描述符
  41. detector->detectAndCompute( img_scene, noArray(), keypoints_scene, descriptors_scene ); //在场景图片中检测关键点并计算描述符
  42. //-- Step 2: 通过FLANN匹配器对描述符向量进行匹配
  43. // 由于SURF是一个浮点数描述符,此处使用NORM_L2
  44. Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(DescriptorMatcher::FLANNBASED);
  45. std::vector< std::vector<DMatch> > knn_matches; //定义knn匹配的结果向量
  46. matcher->knnMatch( descriptors_object, descriptors_scene, knn_matches, 2 ); //knn匹配
  47. //-- Step 3: 利用Lowe's比率测试过滤匹配点
  48. const float ratio_thresh = 0.75f;
  49. std::vector<DMatch> good_matches; //定义储存优质匹配点的向量
  50. for (size_t i = 0; i < knn_matches.size(); i++)
  51. {
  52. if (knn_matches[i][0].distance < ratio_thresh * knn_matches[i][1].distance) //通过比率测试进行筛选
  53. {
  54. good_matches.push_back(knn_matches[i][0]);
  55. }
  56. }
  57. //-- Step 4: 绘制优质匹配点
  58. Mat img_matches;
  59. drawMatches( img_object, keypoints_object, img_scene, keypoints_scene, good_matches, img_matches, Scalar::all(-1),
  60. Scalar::all(-1), std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
  61. //-- Step 5: 找到场景图片中的目标位置
  62. std::vector<Point2f> obj;
  63. std::vector<Point2f> scene;
  64. for( size_t i = 0; i < good_matches.size(); i++ )
  65. {
  66. //-- 从优质匹配点中获取关键点
  67. obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
  68. scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt );
  69. }
  70. Mat H = findHomography( obj, scene, RANSAC ); //计算单应性矩阵
  71. //-- Step 6: 获取目标图片的角点(the object to be "detected")
  72. std::vector<Point2f> obj_corners(4);
  73. obj_corners[0] = Point2f(0, 0);
  74. obj_corners[1] = Point2f( (float)img_object.cols, 0 );
  75. obj_corners[2] = Point2f( (float)img_object.cols, (float)img_object.rows );
  76. obj_corners[3] = Point2f( 0, (float)img_object.rows );
  77. std::vector<Point2f> scene_corners(4);
  78. perspectiveTransform( obj_corners, scene_corners, H); //对目标点进行透视投影变换
  79. //-- Draw lines between the corners (the mapped object in the scene - image_2 )
  80. line( img_matches, scene_corners[0] + Point2f((float)img_object.cols, 0),
  81. scene_corners[1] + Point2f((float)img_object.cols, 0), Scalar(0, 255, 0), 4 );
  82. line( img_matches, scene_corners[1] + Point2f((float)img_object.cols, 0),
  83. scene_corners[2] + Point2f((float)img_object.cols, 0), Scalar( 0, 255, 0), 4 );
  84. line( img_matches, scene_corners[2] + Point2f((float)img_object.cols, 0),
  85. scene_corners[3] + Point2f((float)img_object.cols, 0), Scalar( 0, 255, 0), 4 );
  86. line( img_matches, scene_corners[3] + Point2f((float)img_object.cols, 0),
  87. scene_corners[0] + Point2f((float)img_object.cols, 0), Scalar( 0, 255, 0), 4 );
  88. //-- Step 7: 展示检测到的匹配
  89. imshow("Good Matches & Object detection", img_matches );
  90. waitKey(); //等待用户按键
  91. return 0;
  92. }
  93. #else
  94. int main()
  95. {
  96. std::cout << "这个教程代码需要xfeatures2d contrib模块才能运行." << std::endl;
  97. return 0;
  98. }
  99. #endif

以上代码实现了一个物体识别程序,它能从一张场景图像中找到另一张目标图像的位置。首先,通过SURF检测器找到两张图片的关键点和描述符。接着,通过FLANN匹配器找到匹配的点,并通过Lowe's比率测试进行筛选,得到优质的匹配点。最后,根据这些匹配点找到目标图片在场景图片中的位置,并在匹配图上绘制出目标的角点

411cb829841d7dbe767d4a38741aa9d9.png

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/344976?site
推荐阅读
相关标签
  

闽ICP备14008679号