[点云分割] Clustering of Pointclouds into Supervoxels

介绍

“Clustering of Pointclouds into Supervoxels” 是一种点云数据聚类的方法,用于将点云数据分割成具有相似特征的超体素(supervoxel)。

超体素是一种在点云数据中表示连续区域的方法,类似于像素在图像中表示连续区域。超体素是点云数据的小块区域,具有相似的几何特征和颜色特征。通过将点云数据聚类成超体素,可以实现对点云数据的语义分割和对象识别。

“Clustering of Pointclouds into Supervoxels” 方法的主要步骤如下:

  1. 首先,对输入的点云数据进行预处理,包括点云滤波、法线估计等操作,以获取点云的几何和颜色特征。

  2. 然后,通过选择一个种子点(seed point)开始,使用一种聚类算法(如欧几里得聚类或基于图的聚类)将点云数据分割成超体素。聚类过程中,会考虑点云的几何和颜色特征,以确保超体素内的点具有相似的特征。

  3. 聚类过程中,可以根据一些准则(如紧密度、颜色一致性等)对超体素进行合并或分割,以进一步优化聚类结果。

  4. 最后,生成的超体素可以用于点云的语义分割、对象识别等应用。可以根据超体素的特征,将点云数据划分为不同的对象或区域。

“Clustering of Pointclouds into Supervoxels” 方法在点云处理和分析中具有广泛的应用,特别是在三维场景理解、目标检测和机器人导航等领域。通过将点云数据聚类为超体素,可以提取出具有语义信息的局部区域,为后续的处理和分析提供更准确和可靠的数据基础。

效果

代码

#include 
#include 
#include 
#include 
#include 
#include 

//VTK include needed for drawing graph lines
#include 

// Types
typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud PointCloudT;
typedef pcl::PointNormal PointNT;
typedef pcl::PointCloud PointNCloudT;
typedef pcl::PointXYZL PointLT;
typedef pcl::PointCloud 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 ("Syntax is: %s  \n "
                                     "--NT Dsables the single cloud transform \n"
                                     "-v \n-s \n"
                                    "-c  \n-z  \n"
                                     "-n \n", argv[0]);
            return (1);
        }


    PointCloudT::Ptr cloud (new PointCloudT);
    pcl::console::print_highlight ("Loading point cloud...\n");
    if (pcl::io::loadPCDFile (argv[1], *cloud))
    {
        pcl::console::print_error ("Error loading cloud file!\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);

    //  //
    // This is how to use supervoxels
    //  //

    pcl::SupervoxelClustering super (voxel_resolution, seed_resolution);
    if (disable_transform)
        super.setUseSingleCameraTransform (false);
    super.setInputCloud (cloud);
    super.setColorImportance (color_importance); // 设置颜色重要性
    super.setSpatialImportance (spatial_importance); // 设置空间重要性
    super.setNormalImportance (normal_importance); // 设置法线重要性

    std::map ::Ptr > supervoxel_clusters;

    pcl::console::print_highlight ("Extracting supervoxels!\n");
    super.extract (supervoxel_clusters);
    pcl::console::print_info ("Found %d supervoxels\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 (); // 获取超体素的体素质心点云
    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.getLabeledVoxelCloud (); // 获取标记过的点云
    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); //获取超体素的法线点云
    //We have this disabled so graph is easy to see, uncomment to see supervoxel normals
    //viewer->addPointCloudNormals (sv_normal_cloud,1,0.05f, "supervoxel_normals");

    pcl::console::print_highlight ("Getting supervoxel adjacency\n");
    std::multimap supervoxel_adjacency;
    super.getSupervoxelAdjacency (supervoxel_adjacency); // 获取超体素的邻接关系
    //To make a graph of the supervoxel adjacency, we need to iterate through the supervoxel adjacency multimap
    or (auto label_itr = supervoxel_adjacency.cbegin (); label_itr != supervoxel_adjacency.cend (); )
    {
        //First get the label
        std::uint32_t supervoxel_label = label_itr->first;
        //Now get the supervoxel corresponding to the label
        pcl::Supervoxel::Ptr supervoxel = supervoxel_clusters.at (supervoxel_label);

        //Now we need to iterate through the adjacent supervoxels and make a point cloud of them
        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::Ptr neighbor_supervoxel = supervoxel_clusters.at (adjacent_itr->second);
            adjacent_supervoxel_centers.push_back (neighbor_supervoxel->centroid_);
            }
        //Now we make a name for this polygon
            std::stringstream ss;
        ss << "supervoxel_" << supervoxel_label;
        //This function is shown below, but is beyond the scope of this tutorial - basically it just generates a "star" polygon mesh from the points given
            addSupervoxelConnectionsToViewer (supervoxel->centroid_, adjacent_supervoxel_centers, ss.str (), viewer);
        //Move iterator forward to next label
        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 points = vtkSmartPointer::New ();
    vtkSmartPointer cells = vtkSmartPointer::New ();
    vtkSmartPointer polyLine = vtkSmartPointer::New ();

    //Iterate through all adjacent points, and add a center point to adjacent point pair
        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);
        }
    // Create a polydata to store everything in
        vtkSmartPointer polyData = vtkSmartPointer::New ();
    // Add the points to the dataset
        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);
    // Add the lines to the dataset
        polyData->SetLines (cells);
    viewer->addModelFromPolyData (polyData,supervoxel_name);
    }

 

你可能感兴趣的:(点云,机器学习,人工智能)