问题描述
在使用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);
} else if (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仓库