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)
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