• 【PCL-11】提取平面上层的目标物,剔除平面下层目标物


    因项目需求,需提取平面上的物体,不提取平面下的物体,尝试采用超体聚类+LCCP分割的方式,但由于上层点云模型一侧有空洞,导致分割效果不理想。

    这里采用pcl::ExtractPolygonalPrismData类,实现平面上物体的提取。
    pcl::ExtractPolygonalPrismData类是通过设定处于同一平面模型上的点索引向量,并指定一定高度,利用指定的点形成二维凸包,再结合指定高度生成多边形棱柱模型,分割出该棱柱的内部点集。
    1、生成凸包

    1. pcl::ConvexHull<pcl::PointXYZ> hull;
    2. hull.setInputCloud(plane);
    3. //重构的维度,若设置为2,则表示计算平面上的凸包
    4. hull.setDimension(2);
    5. //执行凸包重构,将结果存储在convexHull指向的点云中
    6. hull.reconstruct(*convexHull);

    2、构建棱柱模型及分割

    1. // 该类用于分割出棱柱模型内部的点集
    2. pcl::ExtractPolygonalPrismData<pcl::PointXYZ> prism;
    3. prism.setInputCloud(cloud);
    4. // 设置平面模型的点集
    5. prism.setInputPlanarHull(convexHull);
    6. // 设置高度范围
    7. prism.setHeightLimits(35.0f, 500.0f);
    8. pcl::PointIndices::Ptr objectIndices(new pcl::PointIndices);
    9. prism.segment(*objectIndices);
    10. // 分割目标物
    11. extract.setIndices(objectIndices);
    12. extract.filter(*objects);

    完整示例代码:

    1. #include <pcl/io/pcd_io.h>
    2. #include <pcl/sample_consensus/method_types.h>
    3. #include <pcl/sample_consensus/model_types.h>
    4. #include <pcl/segmentation/sac_segmentation.h>
    5. #include <pcl/filters/extract_indices.h>
    6. #include <pcl/surface/convex_hull.h>
    7. #include <pcl/segmentation/extract_polygonal_prism_data.h>
    8. #include <pcl/visualization/cloud_viewer.h>
    9. #include <iostream>
    10. int
    11. main(int argc, char** argv)
    12. {
    13.     pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    14.     pcl::PointCloud<pcl::PointXYZ>::Ptr plane(new pcl::PointCloud<pcl::PointXYZ>);
    15.     pcl::PointCloud<pcl::PointXYZ>::Ptr convexHull(new pcl::PointCloud<pcl::PointXYZ>);
    16.     pcl::PointCloud<pcl::PointXYZ>::Ptr objects(new pcl::PointCloud<pcl::PointXYZ>);
    17.     if (pcl::io::loadPCDFile<pcl::PointXYZ>("..\\testdata\\result\\cylinder.pcd", *cloud) != 0)
    18.     {
    19.         return -1;
    20.     }
    21.     pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
    22.     // 采样一致性算法实现的分割类
    23.     pcl::SACSegmentation<pcl::PointXYZ> segmentation;
    24.     segmentation.setInputCloud(cloud);
    25.     // 设置构造的几何模型类型
    26.     segmentation.setModelType(pcl::SACMODEL_PLANE);
    27.     // 设置采样一致性方法类型
    28.     segmentation.setMethodType(pcl::SAC_RANSAC);
    29.     // 设置点到模型的距离阈值
    30.     segmentation.setDistanceThreshold(10);
    31.     // 设置模型参数优化
    32.     segmentation.setOptimizeCoefficients(true);
    33.     pcl::PointIndices::Ptr planeIndices(new pcl::PointIndices);
    34.     segmentation.segment(*planeIndices, *coefficients);
    35.     if (planeIndices->indices.size() == 0)
    36.         std::cout << "Could not find a plane in the scene." << std::endl;
    37.     else
    38.     {
    39.         // Copy the points of the plane to a new cloud.
    40.         pcl::ExtractIndices<pcl::PointXYZ> extract;
    41.         extract.setInputCloud(cloud);
    42.         extract.setIndices(planeIndices);
    43.         extract.filter(*plane);
    44.         // 保存平面点云
    45.         pcl::io::savePCDFile("..\\testdata\\result\\data\\plane.pcd", *plane);
    46.         // 生成凸包
    47.         pcl::ConvexHull<pcl::PointXYZ> hull;
    48.         hull.setInputCloud(plane);
    49.         //重构的维度,若设置为2,则表示计算平面上的凸包
    50.         hull.setDimension(2);
    51.         hull.reconstruct(*convexHull);
    52.         //pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color_handler(cloud, 255, 188, 255);
    53.         //pcl::visualization::PCLVisualizer viewer("Cloud Viewer");
    54.         viewer.addPointCloud<pcl::PointXYZ>(cloud, "原始点云");
    55.         //viewer.addPointCloud<pcl::PointXYZ>(convexHull, color_handler, "凸包点云");
    56.         //viewer.spin();
    57.         // 冗余检查.检查凸包的维度是否为2
    58.         if (hull.getDimension() == 2)
    59.         {
    60.             // 该类用于分割出棱柱模型内部的点集
    61.             pcl::ExtractPolygonalPrismData<pcl::PointXYZ> prism;
    62.             prism.setInputCloud(cloud);
    63.             // 设置平面模型的点集
    64.             prism.setInputPlanarHull(convexHull);
    65.             // 设置高度范围
    66.             prism.setHeightLimits(35.0f, 500.0f);
    67.             pcl::PointIndices::Ptr objectIndices(new pcl::PointIndices);
    68.             prism.segment(*objectIndices);
    69.             // Get and show all points retrieved by the hull.
    70.             extract.setIndices(objectIndices);
    71.             extract.filter(*objects);
    72.             //可视化
    73.             pcl::visualization::CloudViewer viewerObjects("Objects on table");
    74.             viewerObjects.showCloud(objects);
    75.             pcl::io::savePCDFile("..\\testdata\\result\\data\\objects.pcd", *objects);
    76.             while (!viewerObjects.wasStopped())
    77.             {
    78.                 // Do nothing but wait.
    79.             }
    80.         }
    81.         else std::cout << "The chosen hull is not planar." << std::endl;
    82.     }
    83.     return 0;
    84. }

    运行效果:

    构建三维凸包,分割效果不理想,更换二维凸包后,效果较好。

  • 相关阅读:
    【C++ 程序】级数求和
    【HMS core】【FAQ】【Account Kit】典型问题集2
    分析脚手架、ref、props
    网络模型与细节思维方式
    高性能Java对象转换工具MapStruct
    分享从零开始学习网络设备配置--2.1 交换机基本配置
    DAY-6 | 牛客-NC107 寻找峰值:二分法巧得峰值
    mac安装maven
    自动化利器 Ansible - 从了解到应用
    毕业设计ASP.NET 2368酒店信息管理系统【程序源码+文档+调试运行】
  • 原文地址:https://blog.csdn.net/WXG1011/article/details/132736505