Search code examples
point-cloud-librarypoint-clouds

hwo to use pcl to achieve that discretizing the 3D point cloud into a 2D grid over the xy plane, not use the voxelgrid?


I want to project the 3D point cloud into a 2D grid over the xy plane, each grid cell size is 20cm*20cm, how to achieve it effectively?

NOT use VoxelGrid method, because I want to retain every point and deal with them in the next step(Gaussian kernel every column and use EM to deal with each grid)


Solution

  • As discussed in the comments, you can achieve what you want with OctreePointCloudPointVector class.

    Here is an example how to use the class:

    #include <pcl/point_cloud.h>
    #include <pcl/io/pcd_io.h>
    #include <pcl/octree/octree_pointcloud_pointvector.h>
    
    using Cloud    = pcl::PointCloud<pcl::PointXYZ>;
    using CloudPtr = Cloud::Ptr;
    
    using OctreeT = pcl::octree::OctreePointCloudPointVector<pcl::PointXYZ>;
    
    int main(int argc, char** argv)
    {
        if(argc < 2)
            return 1;
    
        // load cloud
        CloudPtr cloud(new Cloud);
        pcl::io::loadPCDFile(argv[1], *cloud);
    
        CloudPtr cloud_projected(new Cloud(*cloud));
        // project to XY plane
        for(auto& pt : *cloud_projected)
            pt.z = 0.0f;
    
        // create octree, set resolution to 20cm
        OctreeT octree(0.2);
        octree.setInputCloud(cloud_projected);
        octree.addPointsFromInputCloud();
    
        // we gonna store the indices of the octree leafs here
        std::vector<std::vector<int>> indices_vec;
        indices_vec.reserve(octree.getLeafCount());
    
        // traverse the octree leafs and store the indices
        const auto it_end = octree.leaf_depth_end();
        for(auto it = octree.leaf_depth_begin(); it != it_end; ++it)
        {
            auto leaf = it.getLeafContainer();
            std::vector<int> indices; 
            leaf.getPointIndices(indices);
            indices_vec.push_back(indices);
        }
    
        // save leafs to file
        int cnt = 0;
        for(const auto indices : indices_vec)
        {
            Cloud leaf(*cloud, indices);
            pcl::io::savePCDFileBinary("leaf_" + std::to_string(cnt++) + ".pcd", leaf);
        }
    }
    

    You can see the output by calling pcl_viewer:

    pcl_viewer leaf_*.pcd

    See sample outputsample output