体素滤波
Voxel滤波作为一种很常见的滤波方法,但是其PCL内部代码却值得学习,因此今天转载一篇关于pcl中实现的体素滤波的方法。
基本上参考博客:https://blog.csdn.net/u013630299/article/details/105661194
#### Voxel_grid.h
需要添加头文件:#include <pcl/filters/voxel_grid.h>
必须保证Dx>hx,Dy>hy(这两个条件是必须),第四步的时候是计算voxel空间索引.准确降采样就是在每个voxel索引里面取中值,或者随机取一个点,然后输出的点云就是降采样后的点云.
也就是说,下采样后的点云还是原始点云中的点?❤
Approximate_voxel_grid.h
需要添加头文件:#include <pcl/filters/approximate_voxel_grid.h>
核心源码也比较短,还有待研究。
和exact downsampling的前四步一样,先算出voxel的空间索引
,然后通过哈希函数映射到对应的容器里面,这里假设有100个容器,按照图里面给的例子,以h%container作为hash函数映射的值,放到对应的容器里面,这样的话会出现什么情况呢,16,116对应的容器是一样的,而两个h对应的hx,hy,hz是不一样的,这就是哈希冲突。怎么处理哈希冲突呢?
把原来容器里面的点全都取出来,清空,随机取其中的一个点作为输出,然后把新的点放进来,继续填容器的操作。相当于是拿了100个容器,一直从一堆点里面淘点,10000个点放到100个容器里面必然会有索引的冲突,一有冲突就把之前放进去的点拿出来,随机取一个点作为输出,清空,再往里面放新的点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| template <typename PointT> void pcl::ApproximateVoxelGrid<PointT>::applyFilter (PointCloud &output) { int centroid_size = 4; if (downsample_all_data_) centroid_size = boost::mpl::size<FieldList>::value;
std::vector<pcl::PCLPointField> fields; int rgba_index = -1; rgba_index = pcl::getFieldIndex (*input_, "rgb", fields); if (rgba_index == -1) rgba_index = pcl::getFieldIndex (*input_, "rgba", fields); if (rgba_index >= 0) { rgba_index = fields[rgba_index].offset; centroid_size += 3; }
for (size_t i = 0; i < histsize_; i++) { history_[i].count = 0; history_[i].centroid = Eigen::VectorXf::Zero (centroid_size); } Eigen::VectorXf scratch = Eigen::VectorXf::Zero (centroid_size);
output.points.resize (input_->points.size ()); size_t op = 0; for (size_t cp = 0; cp < input_->points.size (); ++cp) { int ix = static_cast<int> (floor (input_->points[cp].x * inverse_leaf_size_[0])); int iy = static_cast<int> (floor (input_->points[cp].y * inverse_leaf_size_[1])); int iz = static_cast<int> (floor (input_->points[cp].z * inverse_leaf_size_[2])); unsigned int hash = static_cast<unsigned int> ((ix * 7171 + iy * 3079 + iz * 4231) & (histsize_ - 1)); he *hhe = &history_[hash]; if (hhe->count && ((ix != hhe->ix) || (iy != hhe->iy) || (iz != hhe->iz))) { flush (output, op++, hhe, rgba_index, centroid_size); hhe->count = 0; hhe->centroid.setZero (); } hhe->ix = ix; hhe->iy = iy; hhe->iz = iz; hhe->count++;
if (rgba_index >= 0) { pcl::RGB rgb; memcpy (&rgb, (reinterpret_cast<const char *> (&input_->points[cp])) + rgba_index, sizeof (RGB)); scratch[centroid_size-3] = rgb.r; scratch[centroid_size-2] = rgb.g; scratch[centroid_size-1] = rgb.b; } pcl::for_each_type <FieldList> (xNdCopyPointEigenFunctor <PointT> (input_->points[cp], scratch)); hhe->centroid += scratch; } for (size_t i = 0; i < histsize_; i++) { he *hhe = &history_[i]; if (hhe->count) flush (output, op++, hhe, rgba_index, centroid_size); } output.points.resize (op); output.width = static_cast<uint32_t> (output.points.size ()); output.height = 1; output.is_dense = false; }   为什么Dx必须>hx,后面的y也一样,Dx其实就是x的进位,h的表达式类似于hx*1+hy*10+hz*10*10,如果Dx=x了那必然会出现不同范围的点指到同一个索引h里面,譬如假设Dx=10,hx可以等于10,以(hx,hy)作为坐标的话,(0,1)和(10,0)在同一个voxel里面,显然这是不对的。
|
疑问
我之前得到的voxel采样之后就不是原来的点云了,这个假设是怎么来的?