问题描述
在使用PCL的voxelgrid filter时,若点云过大,而设置的voxel比较小,可能会导致voxel的数量超过int32的上限,从而会出现警告:“Leaf size is too small for the input dataset”。
通用解决办法
- 此文提出了几个解决办法:
- 对精度要求没那么高的话,可以将leaf size大小设置大一些。
- 将要降采样的点云先分割成几块、在做降采样。
- 使用 OctreeVoxelGridFilter,参考PCL论坛。
My solution
但上述解决办法我觉得并不好用,因此,我通过更改VoxelGrid的代码,实现了对比较大点云的降采样支持。
具体思路为若voxel数目溢出,则使用二分法将点云分成两块,然后递归调用voxelgrid即可。
- 方案一
更改PCL原始代码,找到“Leaf size is too small for the input dataset. Integer indices would overflow”所在位置,并将if中余下部分更改为以下代码:
pcl::PointCloud<PointT>cloud1,cloud2,cloud1f,cloud2f;pcl::PassThrough<PointT>pass;if(dx>dy&&dx>dz){pass.setInputCloud(input_);pass.setFilterFieldName("x");pass.setFilterLimits(min_p[0],min_p[0]+(max_p[0]-min_p[0])/2);pass.filter(cloud1);pass.setFilterLimitsNegative(true);pass.filter(cloud2);}elseif(dy>dx&&dy>dz){pass.setInputCloud(input_);pass.setFilterFieldName("y");pass.setFilterLimits(min_p[1],min_p[1]+(max_p[1]-min_p[1])/2);pass.filter(cloud1);pass.setFilterLimitsNegative(true);pass.filter(cloud2);}else{pass.setInputCloud(input_);pass.setFilterFieldName("z");pass.setFilterLimits(min_p[2],min_p[2]+(max_p[2]-min_p[2])/2);pass.filter(cloud1);pass.setFilterLimitsNegative(true);pass.filter(cloud2);}VoxelGrid voxelGrid=*this;voxelGrid.setInputCloud(cloud1.makeShared());voxelGrid.filter(cloud1f);voxelGrid.setInputCloud(cloud2.makeShared());voxelGrid.filter(cloud2f);output=cloud1f+cloud2f;return;- 方案二
使用我写好的VoxelGridLarge代码。
由于不同的人的遇到的问题往往不一样,如何往工程中应用建议参考我之前的代码(虽然不是解决leafsize的代码,但往工程中应用的思路和写法是一样的):github仓库 或者 gitee仓库