https://github.com/MNewBie/PCL-Notes/blob/master/chapter10.md

关键点也称为兴趣点,它是2D图像或3D点云或曲面模型上,可以通过定义检测标准来获取的具有稳定性、区别性的点集。从技术上来说,关键点的数量相比于原始点云或图像数据量上减小很多,与局部特征描述子结合一起,组成关键点描述子常用来形成原始数据的紧凑表示,而且不失代表性和描述性,从而加快后续识别、追踪等对数据的处理速度。故而,关键点提取就成为2D与3D信息处理中不可或缺的关键技术。
PCL中pcl_keypoints库目前提供几种常用的关键点检测算法,下面给出几种常用算法的实例。

ISSKeypoint3D

参考文献: Yu Zhong, “Intrinsic shape signatures: A shape descriptor for 3D object recognition,”Computer Vision Workshops (ICCV Workshops), 2009 IEEE 12th International Conference on ,vol., no., pp.689-696, Sept. 27 2009-Oct. 4 2009

  1. #include <pcl/io/pcd_io.h>
  2. #include <pcl/point_types.h>
  3. // 包含相关头文件
  4. #include <pcl/keypoints/iss_3d.h>
  5. #include "resolution.h" // 用于计算模型分辨率
  6. typedef pcl::PointXYZ PointT;
  7. int main(int argc, char** argv)
  8. {
  9. // 读取点云
  10. pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
  11. pcl::io::loadPCDFile(argv[1], *cloud);
  12. std::cout << "original cloud size : " << cloud->size() << std::endl;
  13. double resolution = computeCloudResolution(cloud);
  14. pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
  15. pcl::ISSKeypoint3D<PointT, PointT> iss_detector;
  16. iss_detector.setSearchMethod(tree);
  17. iss_detector.setSalientRadius(6 * resolution);
  18. iss_detector.setNonMaxRadius(4 * resolution);
  19. iss_detector.setThreshold21(0.975);
  20. iss_detector.setThreshold32(0.975);
  21. iss_detector.setMinNeighbors(5);
  22. iss_detector.setNumberOfThreads(4);
  23. iss_detector.setInputCloud(cloud);
  24. pcl::PointCloud<PointT>::Ptr keys(new pcl::PointCloud<PointT>);
  25. iss_detector.compute(*keys);
  26. std::cout << "key points size : " << keys->size() << std::endl;
  27. system("pause");
  28. return 0;
  29. }

HarrisKeypoint3D

HarrisKeypoint3D是对2D的Harris提取关键点算法的一个三维扩展。

  1. #include <pcl/io/pcd_io.h>
  2. #include <pcl/point_types.h>
  3. // 包含相关头文件
  4. #include <pcl/keypoints/harris_3d.h>
  5. #include "resolution.h" // 用于计算模型分辨率
  6. typedef pcl::PointXYZ PointT;
  7. int main(int argc, char** argv)
  8. {
  9. // 读取点云
  10. pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
  11. pcl::io::loadPCDFile(argv[1], *cloud);
  12. std::cout << "original cloud size : " << cloud->size() << std::endl;
  13. double resolution = computeCloudResolution(cloud);
  14. pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
  15. pcl::HarrisKeypoint3D<PointT, pcl::PointXYZI> detector;
  16. pcl::PointCloud<pcl::PointXYZI>::Ptr keypoints_temp(new pcl::PointCloud<pcl::PointXYZI>);
  17. detector.setNonMaxSupression(true);
  18. detector.setRadiusSearch(10 * resolution);
  19. detector.setThreshold(1E-6);
  20. detector.setSearchMethod(tree); // 不写也可以,默认构建kdtree
  21. detector.setInputCloud(cloud);
  22. detector.compute(*keypoints_temp);
  23. pcl::console::print_highlight("Detected %d points !\n", keypoints_temp->size());
  24. pcl::PointCloud<PointT>::Ptr keys(new pcl::PointCloud<pcl::PointXYZ>);
  25. pcl::copyPointCloud(*keypoints_temp, *keys);
  26. system("pause");
  27. return 0;
  28. }

SIFTKeypoint

SIFTKeypoint是对2D的sift算法的一个扩展。参考:David G. Lowe, “Distinctive image features from scale-invariant keypoints,” International Journal of Computer Vision, 60, 2 (2004), pp. 91-110.

  1. #include <pcl/io/pcd_io.h>
  2. #include <pcl/point_types.h>
  3. // 包含相关头文件
  4. #include <pcl/features/normal_3d.h>
  5. #include <pcl/keypoints/sift_keypoint.h>
  6. #include "resolution.h" // 用于计算模型分辨率
  7. typedef pcl::PointXYZ PointT;
  8. int main(int argc, char** argv)
  9. {
  10. // 读取点云
  11. pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
  12. pcl::io::loadPCDFile(argv[1], *cloud);
  13. std::cout << "original cloud size : " << cloud->size() << std::endl;
  14. double resolution = computeCloudResolution(cloud); // 模型分辨率
  15. // 法向量
  16. pcl::NormalEstimation<pcl::PointXYZ, pcl::PointNormal> ne;
  17. pcl::PointCloud<pcl::PointNormal>::Ptr cloud_normals(new pcl::PointCloud<pcl::PointNormal>);
  18. pcl::search::KdTree<pcl::PointXYZ>::Ptr tree_n(new pcl::search::KdTree<pcl::PointXYZ>());
  19. ne.setInputCloud(cloud);
  20. ne.setSearchMethod(tree_n);
  21. // ne.setRadiusSearch(10 * resolution);
  22. ne.setKSearch(50);
  23. ne.compute(*cloud_normals);
  24. // 拷贝数据
  25. for (size_t i = 0; i < cloud_normals->points.size(); ++i)
  26. {
  27. cloud_normals->points[i].x = cloud->points[i].x;
  28. cloud_normals->points[i].y = cloud->points[i].y;
  29. cloud_normals->points[i].z = cloud->points[i].z;
  30. }
  31. // sift参数
  32. const float min_scale = 0.001f;
  33. const int n_octaves = 5; //3
  34. const int n_scales_per_octave = 6; //4
  35. const float min_contrast = 0.001f;
  36. // 使用法向量作为强度计算关键点,还可以是rgb、z值或者自定义,具体参看API
  37. pcl::SIFTKeypoint<pcl::PointNormal, PointT> sift; //PointT 可以是 pcl::PointWithScale包含尺度信息
  38. pcl::PointCloud<PointT> keys;
  39. pcl::search::KdTree<pcl::PointNormal>::Ptr tree(new pcl::search::KdTree<pcl::PointNormal>());
  40. sift.setSearchMethod(tree);
  41. sift.setScales(min_scale, n_octaves, n_scales_per_octave);
  42. sift.setMinimumContrast(min_contrast);
  43. sift.setInputCloud(cloud_normals);
  44. sift.compute(keys);
  45. std::cout << "No of SIFT points in the result are " << keys.points.size() << std::endl;
  46. system("pause");
  47. return 0;
  48. }