Ubuntu 20.04.06 PCL C++学习记录(二十三)

@[TOC]PCL中点云分割模块的学习

学习背景

参考书籍:《点云库PCL从入门到精通》以及官方代码PCL官方代码链接,,PCL版本为1.10.0,CMake版本为3.16,可用点云下载地址

学习内容

基于超体素的点云分割,如何使用 pcl::SupervoxelClustering以及如何使用和可视化邻接信息和超体素本身。 本文所用点云

源代码及所用函数

源代码

//基于超体素的点云分割
#include <pcl/console/parse.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include<pcl/segmentation/supervoxel_clustering.h>
#include<vtkPolyLine.h>//vtk用于绘图头文件

typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud<PointT> PointCloudT;
typedef pcl::PointNormal PointNT;
typedef pcl::PointCloud<PointNT> PointNCloudT;
typedef pcl::PointXYZL PointLT;
typedef pcl::PointCloud<PointLT> PointLCloudT;

void addSupervoxelConnectionsToViewer(PointT &supervoxel_center,PointCloudT &adjacent_supervoxel_centers,
                                        std::string supervoxel_name,pcl::visualization::PCLVisualizer::Ptr &viewer);

int main(int argc,char** argv)
{
    /**********************************************提示消息************************************************/
    if(argc<2)
    {
        pcl::console::print_error ("语法为: %s <pcd-file> \n "

                                "--NT 禁用单视图转换 \n"

                                "-v <体素分辨率>\n-s <种子分辨率>\n"

                                "-c <颜色的权重> \n-z <空间权重> \n"

                                "-n <法线的权重>\n", argv[0]);
    return (1);
    }
    /***********************************************读取PCD文件******************************/
    PointCloudT::Ptr cloud (new PointCloudT);
    pcl::console::print_highlight ("加载点云...\n");
    if (pcl::io::loadPCDFile<PointT> (argv[1], *cloud))
    {
        pcl::console::print_error ("点云文件打不开!\n");
        return (-1);
    }
    /***********************************************设置参数********************************/
    bool disable_transform = pcl::console::find_switch(argc,argv,"--NT");

    float voxel_resolution = 0.008f;
    bool voxel_res_specified = pcl::console::find_switch(argc,argv,"-v");
    if (voxel_res_specified)
    {
        pcl::console::parse(argc,argv,"-v",voxel_resolution);
    }

    float seed_resolution = 0.1f;
    bool seed_res_specified = pcl::console::find_switch(argc,argv,"-s");
    if (seed_res_specified)
    {
        pcl::console::parse (argc, argv, "-s", seed_resolution);
    }

    float color_importance = 0.2f;
    if (pcl::console::find_switch (argc, argv, "-c"))
    {
        pcl::console::parse (argc, argv, "-c", color_importance);
    }   

    float spatial_importance = 0.4f;
    if (pcl::console::find_switch (argc, argv, "-z"))
    {
        pcl::console::parse (argc, argv, "-z", spatial_importance);
    }

    float normal_importance = 1.0f;
    if (pcl::console::find_switch (argc, argv, "-n"))
    {
        pcl::console::parse (argc, argv, "-n", normal_importance);
    }

    /*************************************************超像素**********************************/
    pcl::SupervoxelClustering<PointT> super(voxel_resolution,seed_resolution);//SupervoxelClustering 是 PCL 库中提供的一个类,用于将点云分割成超体素(supervoxels)。
    if(disable_transform)
    {
        super.setUseSingleCameraTransform(false);
    }
    super.setInputCloud(cloud);
    super.setColorImportance(color_importance);//颜色权重
    super.setSpatialImportance(spatial_importance);//空间权重
    super.setNormalImportance(normal_importance);//法线权重

    std::map<std::uint32_t,pcl::Supervoxel<PointT>::Ptr> supervoxel_clusters;//用于存储超体素分割的结果
    pcl::console::print_highlight("提取超体素!\n");
    super.extract(supervoxel_clusters);//执行超体素分割算法,将点云分割为多个超体素,并将结果存储在 supervoxel_clusters 中。
    pcl::console::print_info("找到 %d 个超体素\n",supervoxel_clusters.size());

    /*********************************************显示点云**************************************/
    pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
    viewer->setBackgroundColor (0, 0, 0);
    PointCloudT::Ptr voxel_centroid_cloud = super.getVoxelCentroidCloud();//超像素分割器super中获取体素质心点云,并将其存储在智能指针voxel_centroid_cloud中
    viewer->addPointCloud(voxel_centroid_cloud,"voxel centroids");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,2.0,"voxel centroids");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY,0.95,"voxel centroids");

    PointLCloudT::Ptr labeled_voxel_cloud = super.getLabeledCloud();//从超像素分割器super中获取带有标签的体素点云,并将其存储在智能指针labeled_voxel_cloud中。
    viewer->addPointCloud(labeled_voxel_cloud,"labeled voxels");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY,0.8,"labeled voxels");

    PointNCloudT::Ptr sv_normal_cloud = super.makeSupervoxelNormalCloud(supervoxel_clusters);
    pcl::console::print_highlight ("Getting supervoxel adjacency\n");
    std::multimap<std::uint32_t,std::uint32_t> supervoxel_adjacency;
    super.getSupervoxelAdjacency(supervoxel_adjacency);
    /******************************************************要绘制上体素邻接图,我们需要遍历上体素邻接多图 ***********************/
    for(auto label_itr = supervoxel_adjacency.cbegin();label_itr != supervoxel_adjacency.cend();)
    {
        //首先获取标签
        std::uint32_t supervoxel_label = label_itr->first;
        //现在获取与标签相对应的上象素
        pcl::Supervoxel<PointT>::Ptr supervoxel = supervoxel_clusters.at(supervoxel_label);
        //现在,我们需要遍历相邻的超像素,并为它们制作点云
        PointCloudT adjacent_supervoxel_centers;
        for (auto adjacent_itr = supervoxel_adjacency.equal_range(supervoxel_label).first;adjacent_itr!=supervoxel_adjacency.equal_range(supervoxel_label).second;adjacent_itr++)
        {
            pcl::Supervoxel<PointT>::Ptr neighbor_supervoxel = supervoxel_clusters.at(adjacent_itr->second);
            adjacent_supervoxel_centers.push_back(neighbor_supervoxel->centroid_);
        }
        //现在我们为这个多边形命名
        std::stringstream ss;
        ss << "supervoxel_" << supervoxel_label;
        addSupervoxelConnectionsToViewer (supervoxel->centroid_, adjacent_supervoxel_centers, ss.str (), viewer);
        //将迭代器向前移动到下一个标签
        label_itr = supervoxel_adjacency.upper_bound(supervoxel_label);



    }   
    while(!viewer->wasStopped())
    {
        viewer->spinOnce(100);
    }
    return 0;
}
void addSupervoxelConnectionsToViewer (PointT &supervoxel_center,

                                  PointCloudT &adjacent_supervoxel_centers,

                                  std::string supervoxel_name,

                                  pcl::visualization::PCLVisualizer::Ptr & viewer)

{

    vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New ();
    vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New ();
    vtkSmartPointer<vtkPolyLine> polyLine = vtkSmartPointer<vtkPolyLine>::New ();
    //遍历所有相邻点,并为相邻点对添加一个中心点
    for (auto adjacent_itr = adjacent_supervoxel_centers.begin (); adjacent_itr != adjacent_supervoxel_centers.end (); ++adjacent_itr)
    {
        points->InsertNextPoint (supervoxel_center.data);
        points->InsertNextPoint (adjacent_itr->data);
    }
    //创建一个多数据来存储所有内容
    vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New ();
    //将点添加到数据集中
    polyData->SetPoints (points);
    polyLine->GetPointIds  ()->SetNumberOfIds(points->GetNumberOfPoints ());
    for(unsigned int i = 0; i < points->GetNumberOfPoints (); i++)
        polyLine->GetPointIds ()->SetId (i,i);
    cells->InsertNextCell (polyLine);
    //将线条添加到数据集中
    polyData->SetLines (cells);
    viewer->addModelFromPolyData (polyData,supervoxel_name);

}

CMakeLists.txt

cmake_minimum_required(VERSION 3.16 FATAL_ERROR)#指定CMake的最低版本要求为3.16
project(project)#设置项目名称
find_package(PCL 1.10 REQUIRED)#查找PCL库,要求版本为1.10或更高。
include_directories(${PCL_INCLUDE_DIRS})#将PCL库的头文件目录添加到包含路径中
link_directories(${PCL_LIBRARY_DIRS})#将PCL库的库文件目录添加到链接器搜索路径中。
add_definitions(${PCL_DEFINITIONS})#添加PCL库的编译器定义
add_executable (supervoxel_clustering supervoxel_clustering.cpp)
target_link_libraries (supervoxel_clustering ${PCL_LIBRARIES})#将PCL库链接到可执行文件目标。

运行结果

输入这行命令

 ./supervoxel_clustering milk_cartoon_all_small_clorox.pcd --NT

在这里插入图片描述

函数

  • SupervoxelClustering 是 PCL 库中提供的一个类,用于将点云分割成超体素(supervoxels)。超体素是点云中的一些小区域,每个超体素内的点具有相似的特征,如颜色、法线等。通过超体素分割,可以将点云划分为多个有意义的区域,便于进一步的分析和处理。创建 SupervoxelClustering 对象时,需要指定两个参数:
    1. voxel_resolution:体素分辨率,即每个体素的大小。体素是三维空间中的立方体单元。较小的体素分辨率会生成更多的体素,从而得到更细粒度的超体素分割结果,但会增加计算量。
    2. seed_resolution:种子点分辨率,即每个超体素的种子点之间的最小距离。种子点是超体素的中心点,用于生成超体素。较小的种子点分辨率会生成更多的超体素,但会增加计算量。
  • std::map<std::uint32_t, pcl::Supervoxel<PointT>::Ptr>supervoxel_clusters; 这行代码定义了一个 std::map 类型的变量 supervoxel_clusters,用于存储超体素分割的结果。std::map 是 C++ 标准库中的一个关联容器,它以键值对的形式存储数据,其中每个键(key)都唯一地对应一个值(value)。在这里,std::map 的键类型是 std::uint32_t,表示超体素的标签(label),值类型是 pcl::Supervoxel::Ptr,表示指向超体素对象的智能指针。

补充内容

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值