当前位置:   article > 正文

PCL 提取点云边界轮廓-AC方法、平面轮廓_点云轮廓提取

点云轮廓提取

一、概述

PCL点云边界特征检测 (附完整代码 C++)_pcl计算点云特征值_McQueen_LT的博客-CSDN博客

在点云的边界特征检测(网格模型的边界特征检测已经是一个确定性问题了,见 网格模型边界检测)方面,PCL中有一个针对点云边界的可以称作为是s t a t e − o f − t h e − a r t state-of-the-artstate−of−the−art的方法,这个方法出自 D e t e c t i n g   H o l e s   i n   P o i n t   S e t   S u r f a c e s Detecting\space Holes\space in\space Point\space Set\space SurfacesDetecting Holes in Point Set Surfaces这篇论文,叫做 A n g l e   C r i t e r i o n Angle\ CriterionAngle Criterion,简称 A C ACAC。这篇论文中还提出了另一种检测边界的方法是H a l f d i s c   C r i t e r i o n Halfdisc\ CriterionHalfdisc Criterion,H d C HdCHdC。目前PCL中应该只集成了A C ACAC,因为这个方法确实比H d C HdCHdC好,已经够用了。这两种方法的思路都非常简单,但是却非常有效,而往往流传下来的经典方法都是这种简单有效的方法。

二、AC方法步骤讲解

 

三、AC方法代码

原始点云:

计算步骤

1、计算点云的法向量

2、计算点云的边界

3、显示

代码

  1. int PointCloudBoundary2(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
  2. {
  3. // 1 计算法向量
  4. pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
  5. pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
  6. pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normalEstimation;
  7. normalEstimation.setInputCloud(cloud);
  8. normalEstimation.setSearchMethod(tree);
  9. normalEstimation.setRadiusSearch(0.02); // 法向量的半径
  10. normalEstimation.compute(*normals);
  11. /*pcl计算边界*/
  12. pcl::PointCloud<pcl::Boundary>::Ptr boundaries(new pcl::PointCloud<pcl::Boundary>); //声明一个boundary类指针,作为返回值
  13. boundaries->resize(cloud->size()); //初始化大小
  14. pcl::BoundaryEstimation<pcl::PointXYZ, pcl::Normal, pcl::Boundary> boundary_estimation; //声明一个BoundaryEstimation类
  15. boundary_estimation.setInputCloud(cloud); //设置输入点云
  16. boundary_estimation.setInputNormals(normals); //设置输入法线
  17. pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree_ptr(new pcl::search::KdTree<pcl::PointXYZ>);
  18. boundary_estimation.setSearchMethod(kdtree_ptr); //设置搜寻k近邻的方式
  19. boundary_estimation.setKSearch(30); //设置k近邻数量
  20. boundary_estimation.setAngleThreshold(M_PI * 0.6); //设置角度阈值,大于阈值为边界
  21. boundary_estimation.compute(*boundaries); //计算点云边界,结果保存在boundaries中
  22. cout << "边界点云的点数 : "<< boundaries->size()<< endl;
  23. /*可视化*/
  24. pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_visual(new pcl::PointCloud<pcl::PointXYZRGB>);
  25. pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_boundary(new pcl::PointCloud<pcl::PointXYZRGB>);
  26. cloud_visual->resize(cloud->size());
  27. for (size_t i = 0; i < cloud->size(); i++)
  28. {
  29. cloud_visual->points[i].x = cloud->points[i].x;
  30. cloud_visual->points[i].y = cloud->points[i].y;
  31. cloud_visual->points[i].z = cloud->points[i].z;
  32. if (boundaries->points[i].boundary_point != 0)
  33. {
  34. cloud_visual->points[i].r = 255;
  35. cloud_visual->points[i].g = 0;
  36. cloud_visual->points[i].b = 0;
  37. cloud_boundary->push_back(cloud_visual->points[i]);
  38. }
  39. else
  40. {
  41. cloud_visual->points[i].r = 255;
  42. cloud_visual->points[i].g = 255;
  43. cloud_visual->points[i].b = 255;
  44. }
  45. }
  46. pcl::io::savePCDFileBinaryCompressed("D:\\work\\Pointclouds\\clouds\\all.pcd", *cloud_visual);
  47. pcl::io::savePCDFileBinaryCompressed("D:\\work\\Pointclouds\\clouds\\boundaries.pcd", *cloud_boundary);
  48. return 0;
  49. }

显示

  1. boundary_estimation.setKSearch(30); //设置k近邻数量
  2. boundary_estimation.setAngleThreshold(M_PI * 0.6); //设置角度阈值,大于阈值为边界
  3. boundary_estimation.compute(*boundaries); //计算点云边界,结果保存在boundaries中


M_PI*0.6 

M_PI*0.8

四、平面轮廓

原始点云:

步骤:

1、采用RANSAC提取平面

2、提取平面

代码:

  1. int PointCloudBoundary2(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
  2. {
  3. // 1 计算法向量
  4. pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
  5. pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
  6. pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normalEstimation;
  7. normalEstimation.setInputCloud(cloud);
  8. normalEstimation.setSearchMethod(tree);
  9. normalEstimation.setRadiusSearch(0.02); // 法向量的半径
  10. normalEstimation.compute(*normals);
  11. /*pcl计算边界*/
  12. pcl::PointCloud<pcl::Boundary>::Ptr boundaries(new pcl::PointCloud<pcl::Boundary>); //声明一个boundary类指针,作为返回值
  13. boundaries->resize(cloud->size()); //初始化大小
  14. pcl::BoundaryEstimation<pcl::PointXYZ, pcl::Normal, pcl::Boundary> boundary_estimation; //声明一个BoundaryEstimation类
  15. boundary_estimation.setInputCloud(cloud); //设置输入点云
  16. boundary_estimation.setInputNormals(normals); //设置输入法线
  17. pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree_ptr(new pcl::search::KdTree<pcl::PointXYZ>);
  18. boundary_estimation.setSearchMethod(kdtree_ptr); //设置搜寻k近邻的方式
  19. boundary_estimation.setKSearch(30); //设置k近邻数量
  20. boundary_estimation.setAngleThreshold(M_PI * 0.8); //设置角度阈值,大于阈值为边界
  21. boundary_estimation.compute(*boundaries); //计算点云边界,结果保存在boundaries中
  22. cout << "边界点云的点数 : "<< boundaries->size()<< endl;
  23. /*可视化*/
  24. pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_visual(new pcl::PointCloud<pcl::PointXYZRGB>);
  25. pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_boundary(new pcl::PointCloud<pcl::PointXYZRGB>);
  26. cloud_visual->resize(cloud->size());
  27. for (size_t i = 0; i < cloud->size(); i++)
  28. {
  29. cloud_visual->points[i].x = cloud->points[i].x;
  30. cloud_visual->points[i].y = cloud->points[i].y;
  31. cloud_visual->points[i].z = cloud->points[i].z;
  32. if (boundaries->points[i].boundary_point != 0)
  33. {
  34. cloud_visual->points[i].r = 255;
  35. cloud_visual->points[i].g = 0;
  36. cloud_visual->points[i].b = 0;
  37. cloud_boundary->push_back(cloud_visual->points[i]);
  38. }
  39. else
  40. {
  41. cloud_visual->points[i].r = 255;
  42. cloud_visual->points[i].g = 255;
  43. cloud_visual->points[i].b = 255;
  44. }
  45. }
  46. pcl::io::savePCDFileBinaryCompressed("D:\\work\\Pointclouds\\clouds\\all22.pcd", *cloud_visual);
  47. pcl::io::savePCDFileBinaryCompressed("D:\\work\\Pointclouds\\clouds\\boundaries222.pcd", *cloud_boundary);
  48. return 0;
  49. }
  50. /// <summary>
  51. /// 先提取点云的平面然后在进行边界林廓
  52. /// </summary>
  53. /// <param name="cloud"></param>
  54. /// <returns></returns>
  55. int PlaneCloudContour(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
  56. {
  57. // 0 计算法向量
  58. pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
  59. pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
  60. pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normalEstimation;
  61. normalEstimation.setInputCloud(cloud);
  62. normalEstimation.setSearchMethod(tree);
  63. normalEstimation.setRadiusSearch(0.02); // 法向量的半径
  64. normalEstimation.compute(*normals);
  65. // 1 提出出平面
  66. // 提取平面点云的索引
  67. pcl::PointIndices::Ptr index_plane(new pcl::PointIndices);
  68. pcl::SACSegmentationFromNormals<pcl::PointXYZ, pcl::Normal> sacSegmentationFromNormals;
  69. pcl::ModelCoefficients::Ptr mdelCoefficients_plane(new pcl::ModelCoefficients);
  70. sacSegmentationFromNormals.setInputCloud(cloud);
  71. sacSegmentationFromNormals.setOptimizeCoefficients(true);//设置对估计的模型系数需要进行优化
  72. sacSegmentationFromNormals.setModelType(pcl::SACMODEL_NORMAL_PLANE); //设置分割模型
  73. sacSegmentationFromNormals.setNormalDistanceWeight(0.1);//设置表面法线权重系数
  74. sacSegmentationFromNormals.setMethodType(pcl::SAC_RANSAC);//设置采用RANSAC作为算法的参数估计方法
  75. sacSegmentationFromNormals.setMaxIterations(500); //设置迭代的最大次数
  76. sacSegmentationFromNormals.setDistanceThreshold(0.05); //设置内点到模型的距离允许最大值
  77. sacSegmentationFromNormals.setInputCloud(cloud);
  78. sacSegmentationFromNormals.setInputNormals(normals);
  79. sacSegmentationFromNormals.segment(*index_plane, *mdelCoefficients_plane);
  80. std::cerr << "Plane coefficients: " << *mdelCoefficients_plane << std::endl;
  81. // 点云提取
  82. pcl::ExtractIndices<pcl::PointXYZ> extractIndices;
  83. pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_p(new pcl::PointCloud<pcl::PointXYZ>);
  84. extractIndices.setInputCloud(cloud);
  85. extractIndices.setIndices(index_plane);
  86. extractIndices.setNegative(false);
  87. extractIndices.filter(*cloud_p);
  88. pcl::io::savePCDFileBinaryCompressed("D:\\work\\Pointclouds\\clouds\\planeCloud.pcd",*cloud_p);
  89. // 2
  90. PointCloudBoundary2(cloud_p);
  91. return 0;
  92. }

 结果:

平面点云的轮廓线计算-alpha shapes算法原理和实现_α-shape算法-CSDN博客

双阈值Alpha Shapes算法提取点云建筑物轮廓研究 - 豆丁网

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/764838
推荐阅读
相关标签
  

闽ICP备14008679号