pcl中的体素滤波

体素滤波

  Voxel滤波作为一种很常见的滤波方法,但是其PCL内部代码却值得学习,因此今天转载一篇关于pcl中实现的体素滤波的方法。
基本上参考博客:https://blog.csdn.net/u013630299/article/details/105661194 #### Voxel_grid.h   需要添加头文件:#include <pcl/filters/voxel_grid.h> voxelgrid
  必须保证Dx>hx,Dy>hy(这两个条件是必须),第四步的时候是计算voxel空间索引.准确降采样就是在每个voxel索引里面取中值,或者随机取一个点,然后输出的点云就是降采样后的点云. 也就是说,下采样后的点云还是原始点云中的点?

Approximate_voxel_grid.h

  需要添加头文件:#include <pcl/filters/approximate_voxel_grid.h> 核心源码也比较短,还有待研究。 approximatevoxelgrid   和exact downsampling的前四步一样,先算出voxel的空间索引 ,然后通过哈希函数映射到对应的容器里面,这里假设有100个容器,按照图里面给的例子,以h%container作为hash函数映射的值,放到对应的容器里面,这样的话会出现什么情况呢,16,116对应的容器是一样的,而两个h对应的hx,hy,hz是不一样的,这就是哈希冲突。怎么处理哈希冲突呢?
voxelgrid
  把原来容器里面的点全都取出来,清空,随机取其中的一个点作为输出,然后把新的点放进来,继续填容器的操作。相当于是拿了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;

// ---[ RGB special case
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 output for worst case
size_t op = 0; // output pointer
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 ();// = Eigen::VectorXf::Zero (centroid_size);
}
hhe->ix = ix;
hhe->iy = iy;
hhe->iz = iz;
hhe->count++;

// Unpack the point into scratch, then accumulate
// ---[ RGB special case
if (rgba_index >= 0)
{
// fill r/g/b data
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; // downsampling breaks the organized structure
output.is_dense = false; // we filter out invalid points
}
&emsp;&emsp;为什么Dx必须&gt;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采样之后就不是原来的点云了,这个假设是怎么来的?

| visits
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×