zoukankan      html  css  js  c++  java
  • 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 << "程序退出...........
    ";
     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 << "
    
    
    	欢迎来到重映射示例程序~
    
    ";
    105     cout << "	当前使用的OpenCV版本为 OpenCV "CV_VERSION;
    106     cout <<  "
    
    	按键操作说明: 
    
    "
    107         "		键盘按键【ESC】- 退出程序
    "
    108         "		键盘按键【1】-  第一种映射方式
    "
    109         "		键盘按键【2】- 第二种映射方式
    "
    110         "		键盘按键【3】- 第三种映射方式
    "
    111         "		键盘按键【4】- 第四种映射方式
    "
    112         "
    
    								";
    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函数指定名称的图片存在~! 
    ";
    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 << "
    
    
    	欢迎来到【SURF特征点检测】示例程序~
    
    ";
    59     cout <<  "
    
    	按键操作说明: 
    
    "
    60                 "		键盘按键任意键- 退出程序
    
    "
    61                 "
    
    								";
    62 
    63 }

    效果展示:

    原图:

     

     效果图:

     

     

  • 相关阅读:
    史记 · 码农列传
    死侍在新片中,扮演了一个 AI 驱动的 NPC
    什么是高中物理?一篇长长长长文告诉你!
    你管这玩意叫网络?
    你管这破玩意叫计算机?
    try-catch-finally中的4个巨坑,老程序员也搞不定!
    未来几年,软件测试九大新兴趋势
    代码中大量的if/else,你有什么优化方案?
    PHP部署服务端常见问题整理
    PHP服务端环境搭建
  • 原文地址:https://www.cnblogs.com/Long-w/p/9669687.html
Copyright © 2011-2022 走看看