34、【opencv入门】重映射 & SURF特征点检测合辑

一、SURF特征点检测

1、SURF算法概览

  SURF,英语全称为SpeededUp Robust Features,直译的话就是“加速版的具有鲁棒性的特征“算法,由Bay在2006年首次提出。SURF是尺度不变特征变换算法(SIFT算法)的加速版。一般来说,标准的SURF算子比SIFT算子快好几倍,并且在多幅图片下具有更好的稳定性。SURF最大的特征在于采用了harr特征以及积分图像的概念,这大大加快了程序的运行时间。SURF可以应用于计算机视觉的物体识别以及3D重构中。

下图展示了SUTF类相关的一些继承关系:

2、drawKeypoints函数详解

因为接下来的示例程序需要用到drawKeypoints函数,顾名思义,此函数用于绘制关键点。

C++: void drawKeypoints(const Mat&image, const vector<KeyPoint>& keypoints, Mat& outImage, constScalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT )
第一个参数,const Mat&类型的src,输入图像。
第二个参数,const vector<KeyPoint>&类型的keypoints,根据源图像得到的特征点,它是一个输出参数。
第三个参数,Mat&类型的outImage,输出图像,其内容取决于第五个参数标识符falgs。
第四个参数,const Scalar&类型的color,关键点的颜色,有默认值Scalar::all(-1)。 第五个参数,int类型的flags,绘制关键点的特征标识符,有默认值DrawMatchesFlags::DEFAULT。可以在如下这个结构体中选取值。
 1 struct DrawMatchesFlags
 2 {
 3 enum  4  {  5 DEFAULT = 0, // Output image matrix will be created (Mat::create),  6 // i.e. existing memory of output image may be reused.  7 // Two source images, matches, and single keypoints  8 // will be drawn.  9 // For each keypoint, only the center point will be 10 // drawn (without a circle around the keypoint with the 11 // keypoint size and orientation). 12 DRAW_OVER_OUTIMG = 1, // Output image matrix will not be 13 // created (using Mat::create). Matches will be drawn 14 // on existing content of output image. 15 NOT_DRAW_SINGLE_POINTS = 2, // Single keypoints will not be drawn. 16 DRAW_RICH_KEYPOINTS = 4 // For each keypoint, the circle around 17 // keypoint with keypoint size and orientation will 18 // be drawn. 19  }; 20 };

三、综合示例

1、重映射综合示例

  1 //重映射综合示例
  2 #include "opencv2/highgui/highgui.hpp"  3 #include "opencv2/imgproc/imgproc.hpp"  4 #include <iostream>  5  6 using namespace cv;  7 using namespace std;  8  9 #define WINDOW_NAME "【程序窗口】" //为窗口标题定义的宏  10  11 Mat g_srcImage, g_dstImage;  12 Mat g_map_x, g_map_y;  13  14 int update_map( int key);  15 static void ShowHelpText( );//输出帮助文字  16  17 int main( int argc, char** argv )  18 {  19 //改变console字体颜色  20 system("color 2F");  21  22 //显示帮助文字  23  ShowHelpText();  24  25 //【1】载入原始图  26 g_srcImage = imread( "1.jpg", 1 );  27  28 imshow("原始图",g_srcImage);  29  30 //【2】创建和原始图一样的效果图,x重映射图,y重映射图  31  g_dstImage.create( g_srcImage.size(), g_srcImage.type() );  32  g_map_x.create( g_srcImage.size(), CV_32FC1 );  33  g_map_y.create( g_srcImage.size(), CV_32FC1 );  34  35 //【3】创建窗口并显示  36  namedWindow( WINDOW_NAME, CV_WINDOW_AUTOSIZE );  37  imshow(WINDOW_NAME,g_srcImage);  38  39 //【4】轮询按键,更新map_x和map_y的值,进行重映射操作并显示效果图  40 while( 1 )  41  {  42 //获取键盘按键  43 int key = waitKey(0);  44  45 //判断ESC是否按下,若按下便退出  46 if( (key & 255) == 27 )  47  {  48 cout << "程序退出...........\n";  49 break;  50  }  51  52 //根据按下的键盘按键来更新 map_x & map_y的值. 然后调用remap( )进行重映射  53  update_map(key);  54 remap( g_srcImage, g_dstImage, g_map_x, g_map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0) );  55  56 //显示效果图  57  imshow( WINDOW_NAME, g_dstImage );  58  }  59 return 0;  60 }  61  62 int update_map( int key )  63 {  64 //双层循环,遍历每一个像素点  65 for( int j = 0; j < g_srcImage.rows;j++)  66  {  67 for( int i = 0; i < g_srcImage.cols;i++)  68  {  69 switch(key)  70  {  71 case '1': // 键盘【1】键按下,进行第一种重映射操作  72 if( i > g_srcImage.cols*0.25 && i < g_srcImage.cols*0.75 && j > g_srcImage.rows*0.25 && j < g_srcImage.rows*0.75) 73 { 74 g_map_x.at<float>(j,i) = static_cast<float>(2*( i - g_srcImage.cols*0.25 ) + 0.5); 75 g_map_y.at<float>(j,i) = static_cast<float>(2*( j - g_srcImage.rows*0.25 ) + 0.5); 76 } 77 else 78 { 79 g_map_x.at<float>(j,i) = 0; 80 g_map_y.at<float>(j,i) = 0; 81 } 82 break; 83 case '2':// 键盘【2】键按下,进行第二种重映射操作 84 g_map_x.at<float>(j,i) = static_cast<float>(i); 85 g_map_y.at<float>(j,i) = static_cast<float>(g_srcImage.rows - j); 86 break; 87 case '3':// 键盘【3】键按下,进行第三种重映射操作 88 g_map_x.at<float>(j,i) = static_cast<float>(g_srcImage.cols - i); 89 g_map_y.at<float>(j,i) = static_cast<float>(j); 90 break; 91 case '4':// 键盘【4】键按下,进行第四种重映射操作 92 g_map_x.at<float>(j,i) = static_cast<float>(g_srcImage.cols - i); 93 g_map_y.at<float>(j,i) = static_cast<float>(g_srcImage.rows - j); 94 break; 95 } 96 } 97 } 98 return 1; 99 } 100 101 static void ShowHelpText() 102 { 103 //输出一些帮助信息 104 cout << "\n\n\n\t欢迎来到重映射示例程序~\n\n"; 105 cout << "\t当前使用的OpenCV版本为 OpenCV "CV_VERSION; 106 cout << "\n\n\t按键操作说明: \n\n" 107 "\t\t键盘按键【ESC】- 退出程序\n" 108 "\t\t键盘按键【1】- 第一种映射方式\n" 109 "\t\t键盘按键【2】- 第二种映射方式\n" 110 "\t\t键盘按键【3】- 第三种映射方式\n" 111 "\t\t键盘按键【4】- 第四种映射方式\n" 112 "\n\n\t\t\t\t\t\t\t\t"; 113 }

2、SURF特征点检测综合示例程序

这个示例程涉及到如下三个方面:

1 使用 FeatureDetector 接口来发现感兴趣点。
2 使用 SurfFeatureDetector 以及其函数 detect 来实现检测过程
3 使用函数 drawKeypoints 绘制检测到的关键点。
 1 //SURF特征点检测完整示例
 2 #include "opencv2/core/core.hpp"  3 #include "opencv2/features2d/features2d.hpp"  4 #include "opencv2/highgui/highgui.hpp"  5 #include "opencv2/nonfree/nonfree.hpp"  6 #include <iostream>  7  8 using namespace std;  9 using namespace cv; 10 11 12 static void ShowHelpText( );//输出帮助文字 13 14 int main( int argc, char** argv ) 15 { 16 //【0】改变console字体颜色 17 system("color 2F"); 18 19 //【0】显示帮助文字 20  ShowHelpText( ); 21 22 //【1】载入源图片并显示 23 Mat srcImage1 = imread("1.jpg", 1 ); 24 Mat srcImage2 = imread("2.jpg", 1 ); 25 if( !srcImage1.data || !srcImage2.data )//检测是否读取成功 26  { 27 cout << "读取图片错误,请确定目录下是否有imread函数指定名称的图片存在~! \n"; 28 return false; 29  } 30 imshow("原始图1",srcImage1); 31 imshow("原始图2",srcImage2); 32 33 //【2】定义需要用到的变量和类 34 int minHessian = 400;//定义SURF中的hessian阈值特征点检测算子 35 SurfFeatureDetector detector( minHessian );//定义一个SurfFeatureDetector(SURF) 特征检测类对象 36 std::vector<KeyPoint> keypoints_1, keypoints_2;//vector模板类是能够存放任意类型的动态数组,能够增加和压缩数据 37 38 //【3】调用detect函数检测出SURF特征关键点,保存在vector容器中 39  detector.detect( srcImage1, keypoints_1 ); 40  detector.detect( srcImage2, keypoints_2 ); 41 42 //【4】绘制特征关键点 43  Mat img_keypoints_1; Mat img_keypoints_2; 44 drawKeypoints( srcImage1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT ); 45 drawKeypoints( srcImage2, keypoints_2, img_keypoints_2, Scalar::all(-1), DrawMatchesFlags::DEFAULT ); 46 47 //【5】显示效果图 48 imshow("特征点检测效果图1", img_keypoints_1 ); 49 imshow("特征点检测效果图2", img_keypoints_2 ); 50 51 waitKey(0); 52 return 0; 53 } 54 55 void ShowHelpText() 56 { 57 //输出一些帮助信息 58 cout << "\n\n\n\t欢迎来到【SURF特征点检测】示例程序~\n\n"; 59 cout << "\n\n\t按键操作说明: \n\n" 60 "\t\t键盘按键任意键- 退出程序\n\n" 61 "\n\n\t\t\t\t\t\t\t\t"; 62 63 }

效果展示:

原图:

 

 效果图:

 

 

猜你喜欢

转载自www.cnblogs.com/Long-w/p/9669687.html