基於SIFT的點雲關鍵點提取

這篇博文主要介紹SIFT算法在提取點雲圖像關鍵點時的具體用法,轉載於http://www.cnblogs.com/freshmen/p/4254573.html。

      尺度不變特徵轉換(Scale-invariant feature transform,SIFT)是David Lowe在1999年發表,2004年總結完善。其應用範圍包括物體辨識,機器人地圖感知與導航、3D模型建立、手勢辨識、影像追蹤和動作對比。此算法已經申請專利,專利擁有者屬於英屬哥倫比亞大學。SIFT算法在3D數據上的應用由Flint等在2007年實現。這裏所講的提取點雲關鍵點的算法便是由Flint等人實現的SIFT3D算法。

      其實現代如下:  

// STL
#include <iostream>

// PCL
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <pcl/keypoints/sift_keypoint.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/console/time.h>

/* This examples shows how to estimate the SIFT points based on the 
 * z gradient of the 3D points than using the Intensity gradient as
 * usually used for SIFT keypoint estimation.
 */

namespace pcl
{
  template<>
    struct SIFTKeypointFieldSelector<PointXYZ>
    {
      inline float
      operator () (const PointXYZ &p) const
      {
    return p.z;
      }
    };
}

int
main(int, char** argv)
{
  std::string filename = argv[1];
  std::cout << "Reading " << filename << std::endl;
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xyz (new pcl::PointCloud<pcl::PointXYZ>);
  if(pcl::io::loadPCDFile<pcl::PointXYZ> (filename, *cloud_xyz) == -1) // load the file
  {
    PCL_ERROR ("Couldn't read file");
    return -1;
  }
  std::cout << "points: " << cloud_xyz->points.size () <<std::endl;
  
  // Parameters for sift computation
  const float min_scale = 0.005f; //the standard deviation of the smallest scale in the scale space
  const int n_octaves = 6;//the number of octaves (i.e. doublings of scale) to compute
  const int n_scales_per_octave = 4;//the number of scales to compute within each octave
  const float min_contrast = 0.005f;//the minimum contrast required for detection
  
  pcl::console::TicToc time;
  time.tic();
  // Estimate the sift interest points using z values from xyz as the Intensity variants
  pcl::SIFTKeypoint<pcl::PointXYZ, pcl::PointWithScale> sift;
  pcl::PointCloud<pcl::PointWithScale> result;
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ> ());
  sift.setSearchMethod(tree);
  sift.setScales(min_scale, n_octaves, n_scales_per_octave);
  sift.setMinimumContrast(min_contrast);
  sift.setInputCloud(cloud_xyz);
  sift.compute(result);
  std::cout<<"Computing the SIFT points takes "<<time.toc()/1000<<"seconds"<<std::endl;
  std::cout << "No of SIFT points in the result are " << result.points.size () << std::endl;

  // Copying the pointwithscale to pointxyz so as visualize the cloud
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_temp (new pcl::PointCloud<pcl::PointXYZ>);
  copyPointCloud(result, *cloud_temp);
  std::cout << "SIFT points in the result are " << cloud_temp->points.size () << std::endl;
  // Visualization of keypoints along with the original cloud
  pcl::visualization::PCLVisualizer viewer("PCL Viewer");
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> keypoints_color_handler (cloud_temp, 0, 255, 0);
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color_handler (cloud_xyz, 255, 0, 0);
  viewer.setBackgroundColor( 0.0, 0.0, 0.0 );
  viewer.addPointCloud(cloud_xyz, cloud_color_handler, "cloud");//add point cloud
  viewer.addPointCloud(cloud_temp, keypoints_color_handler, "keypoints");//add the keypoints 
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 7, "keypoints");
  
  while(!viewer.wasStopped ())
  {
    viewer.spinOnce ();
  }
  return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章