使用OpenCV自带函数实现特征点和描述子的计算,对比运行速度

环境

我在XP(32bit)电脑上搭建了Visual Studio 2010和OpenCV-3.1.0,OpenCV包含了OpenCV_contrib这个包。

OpenCV-3.1.0自带了6种能同时计算特征点和描述子的算法(笔者浏览了一遍,目测有6个函数)。分别是cv::xfeatures2d::SIFT、cv::xfeatures2d::SURF、cv::AKAZE、cv::BRISK、cv::KAZE、cv::ORB。

使用cv::xfeatures2d::SIFT、cv::xfeatures2d::SURF盈利的话,传闻是有专利问题的。

代码和图片来源

在OpenCV-3.1.0的说明文档找到SURF例程,此处是链接。稍作修改,就可以编写一段对比多种算法的程序。而图片直接使用TUM的rgbd-dataset。此处是链接

经过修改后的代码

以下直接上代码。代码介绍:使用dataset内,最简单的一段“xyz”。读取头两帧RGB图像。分别用上述六种方法计算特征点和描述子。对比不同方法的速度。

#include <stdio.h>
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/xfeatures2d.hpp"
#include "opencv2/highgui.hpp"

#include <ctime>
using namespace cv;
using namespace cv::xfeatures2d;
void readme();
/* @function main */
int main( int argc, char** argv )
{
	
  std::cout << std::endl << "< Reading images..." << std::endl;  

  Mat img_1 = imread( "D:\\rgbd_dataset_freiburg1_xyz\\rgb\\1305031102.175304.png", IMREAD_GRAYSCALE );
  Mat img_2 = imread( "D:\\rgbd_dataset_freiburg1_xyz\\rgb\\1305031102.211214.png", IMREAD_GRAYSCALE );
  if( argc == 3 )
  { 
	  Mat img_1 = imread( argv[1], IMREAD_GRAYSCALE );
	  Mat img_2 = imread( argv[2], IMREAD_GRAYSCALE );
	  //readme(); return -1; 
  }
  else
  {
	  //readme();	  
  }

  if( !img_1.data || !img_2.data )
  { std::cout<< " --(!) Error reading images " << std::endl; return -1; }

  //-- Step 1: Detect the keypoints using SURF Detector
  int minHessian = 400;
  //Ptr<SURF> detector = SURF::create( minHessian );


  std::vector<KeyPoint> keypoints_1, keypoints_2;
  std::vector<KeyPoint> keypoints_11, keypoints_22;
  std::vector<KeyPoint> keypoints_111, keypoints_222;
  std::vector<KeyPoint> keypoints_1111, keypoints_2222;
  std::vector<KeyPoint> keypoints_11111, keypoints_22222;
  std::vector<KeyPoint> keypoints_111111, keypoints_222222;

  
  clock_t time_stt = clock();
  std::cout << std::endl << "< Extracting keypoints from images using SIFT..." << std::endl;  
  Ptr<SIFT> detector = SIFT::create(  );
  detector->detect( img_1, keypoints_1 );
  detector->detect( img_2, keypoints_2 );  
  std::cout <<"img1:"<< keypoints_1.size() << " points  img2:" <<keypoints_2.size()   
        << " points" << std::endl;
  std::cout << "time use in SIFT is " << 1000 * (clock() - time_stt)/(double)CLOCKS_PER_SEC << "ms" << std::endl;  
  std::cout << "time of per keypoints is " << 1000 * (clock() - time_stt)/(double)CLOCKS_PER_SEC / (keypoints_1.size() + keypoints_2.size()) << "ms" << std::endl;
  std::cout <<  ">" << std::endl; 

  time_stt = clock();
  std::cout << std::endl << "< Extracting keypoints from images using SURF..." << std::endl;  
  Ptr<SURF> detectorSURF = SURF::create(  );
  detectorSURF->detect( img_1, keypoints_11 );
  detectorSURF->detect( img_2, keypoints_22 );
  std::cout <<"img11:"<< keypoints_11.size() << " points  img22:" <<keypoints_22.size()   
        << " points" << std::endl << ">" << std::endl;  
  std::cout << "time use in SURF is " << 1000 * (clock() - time_stt)/(double)CLOCKS_PER_SEC << "ms" << std::endl;
  std::cout << "time of per keypoints is " << 1000 * (clock() - time_stt)/(double)CLOCKS_PER_SEC / (keypoints_11.size() + keypoints_22.size()) << "ms" << std::endl;
  std::cout <<  ">" << std::endl; 

  
  time_stt = clock();
  std::cout << std::endl << "< Extracting keypoints from images using ORB..." << std::endl;  
  Ptr<ORB> detectorORB = ORB::create(  );
  detectorORB->detect( img_1, keypoints_111 );
  detectorORB->detect( img_2, keypoints_222 );
  std::cout <<"img111:"<< keypoints_111.size() << " points  img222:" <<keypoints_222.size()   
        << " points" << std::endl ;
  std::cout << "time use in ORB is " << 1000 * (clock() - time_stt)/(double)CLOCKS_PER_SEC << "ms" << std::endl;
  std::cout << "time of per keypoints is " << 1000 * (clock() - time_stt)/(double)CLOCKS_PER_SEC / (keypoints_111.size() + keypoints_222.size()) << "ms" << std::endl;
  std::cout <<  ">" << std::endl; 
  
  time_stt = clock();
  std::cout << std::endl << "< Extracting keypoints from images using AKAZE..." << std::endl;  
  Ptr<AKAZE> detectorAKAZE = AKAZE::create(  );
  detectorAKAZE->detect( img_1, keypoints_1111 );
  detectorAKAZE->detect( img_2, keypoints_2222 );
  std::cout <<"img1111:"<< keypoints_1111.size() << " points  img2222:" <<keypoints_2222.size()   
        << " points" << std::endl; 
  std::cout << "time use in AKAZE is " << 1000 * (clock() - time_stt)/(double)CLOCKS_PER_SEC << "ms" << std::endl;
  std::cout << "time of per keypoints is " << 1000 * (clock() - time_stt)/(double)CLOCKS_PER_SEC / (keypoints_1111.size() + keypoints_2222.size()) << "ms" << std::endl;
  std::cout <<  ">" << std::endl; 
  
  time_stt = clock();
  std::cout << std::endl << "< Extracting keypoints from images using BRISK..." << std::endl;  
  Ptr<BRISK> detectorBRISK = BRISK::create(  );
  detectorBRISK->detect( img_1, keypoints_11111 );
  detectorBRISK->detect( img_2, keypoints_22222 );
  std::cout <<"img11111:"<< keypoints_11111.size() << " points  img22222:" <<keypoints_22222.size()   
        << " points" << std::endl;
  std::cout << "time use in BRISK is " << 1000 * (clock() - time_stt)/(double)CLOCKS_PER_SEC << "ms" << std::endl;
  std::cout << "time of per keypoints is " << 1000 * (clock() - time_stt)/(double)CLOCKS_PER_SEC / (keypoints_11111.size() + keypoints_22222.size()) << "ms" << std::endl;
  std::cout <<  ">" << std::endl; 

  
  time_stt = clock();
  std::cout << std::endl << "< Extracting keypoints from images using KAZE..." << std::endl;  
  Ptr<KAZE> detectorKAZE = KAZE::create(  );
  detectorKAZE->detect( img_1, keypoints_111111 );
  detectorKAZE->detect( img_2, keypoints_222222 );
  std::cout <<"img111111:"<< keypoints_111111.size() << " points  img222222:" <<keypoints_222222.size()   
        << " points" << std::endl;  
  std::cout << "time use in KAZE is " << 1000 * (clock() - time_stt)/(double)CLOCKS_PER_SEC << "ms" << std::endl;
  std::cout << "time of per keypoints is " << 1000 * (clock() - time_stt)/(double)CLOCKS_PER_SEC / (keypoints_111111.size() + keypoints_222222.size()) << "ms" << std::endl;
  std::cout <<  ">" << std::endl; 
  


  //-- Draw keypoints
  Mat img_keypoints_1; 
  Mat img_keypoints_2;
  Mat img_keypoints_11; 
  Mat img_keypoints_22;
  Mat img_keypoints_111; 
  Mat img_keypoints_222;
  Mat img_keypoints_1111; 
  Mat img_keypoints_2222;
  Mat img_keypoints_11111; 
  Mat img_keypoints_22222;
  Mat img_keypoints_111111; 
  Mat img_keypoints_222222;
  drawKeypoints( img_1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
  drawKeypoints( img_2, keypoints_2, img_keypoints_2, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
  drawKeypoints( img_1, keypoints_11, img_keypoints_11, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
  drawKeypoints( img_2, keypoints_22, img_keypoints_22, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
  drawKeypoints( img_1, keypoints_111, img_keypoints_111, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
  drawKeypoints( img_2, keypoints_222, img_keypoints_222, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
  drawKeypoints( img_1, keypoints_1111, img_keypoints_1111, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
  drawKeypoints( img_2, keypoints_2222, img_keypoints_2222, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
  drawKeypoints( img_1, keypoints_11111, img_keypoints_11111, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
  drawKeypoints( img_2, keypoints_22222, img_keypoints_22222, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
  drawKeypoints( img_1, keypoints_111111, img_keypoints_111111, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
  drawKeypoints( img_2, keypoints_222222, img_keypoints_222222, Scalar::all(-1), DrawMatchesFlags::DEFAULT );


  //-- Show detected (drawn) keypoints
  
  imshow("Keypoints 1", img_keypoints_1 );
  imshow("Keypoints 2", img_keypoints_2 );
  /*
  imshow("Keypoints 11", img_keypoints_11 );
  imshow("Keypoints 22", img_keypoints_22 );
  imshow("Keypoints 111", img_keypoints_111 );
  imshow("Keypoints 222", img_keypoints_222 );
  imshow("Keypoints 1111", img_keypoints_1111 );
  imshow("Keypoints 2222", img_keypoints_2222 );
  imshow("Keypoints 11111", img_keypoints_11111 );
  imshow("Keypoints 22222", img_keypoints_22222 );
  imshow("Keypoints 111111", img_keypoints_111111 );
  imshow("Keypoints 222222", img_keypoints_222222 );
  */
  waitKey(0);
  return 0;
  }
  /* @function readme */
  void readme()
  { std::cout << " Usage: ./SURF_detector <img1> <img2>" << std::endl; }

程序运行结果见下表。

OpenCV自带6个计算特征点和描述子的函数之运算速度对比
函数 计算得到图片1的特征点数量(个) 计算得到图片1的特征点数量(个) 耗时(ms) 平均每个特征点耗时(ms)
SIFT 2006 1596 2125 0.6030
SURF 1908 1686 735 0.2045
ORB 500 500 109 0.1100
AKAZE 1454 1280 1750 0.6456
BRISK 2516 1928 1078 0.2568
KAZE 1742 1556 5937 1.8193

由于是同时计算两张图片,对比之前翻过的其他前辈做过的实验,耗时比较长。

本机XP,CPU是 Intel Core 2 DUo CPU E7300 @2.66GHz。2G内存。

本文没有干货……干货请看参考资料。

参考1:Feature Description,https://docs.opencv.org/3.1.0/d5/dde/tutorial_feature_description.html

参考2:RGB-D SLAM Dataset and Benchmark,https://vision.in.tum.de/data/datasets/rgbd-dataset

参考3:OpenCV特征点提取算法对比,http://www.p-chao.com/2017-06-14/opencv%e7%89%b9%e5%be%81%e7%82%b9%e6%8f%90%e5%8f%96%e7%ae%97%e6%b3%95%e5%af%b9%e6%af%94/

参考4:学习OpenCV——BOW特征提取函数(特征点篇),http://www.cnblogs.com/GarfieldEr007/p/5401859.html

参考5:Oriented FAST and Rotated BRIEF,http://www.cnblogs.com/ronny/p/4083537.html

猜你喜欢

转载自blog.csdn.net/qq_27158179/article/details/81178427