New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[VoxelGrid] Downsampling produces wrong result #5339
Comments
The data you are using seems to be the problem. I extended your test: #include <pcl/point_types.h>
#include <pcl/filters/filter.h>
#include <pcl/filters/voxel_grid.h>
using namespace pcl;
using namespace pcl::io;
using namespace Eigen;
int main()
{
const size_t size = 1000;
#if 0
PointCloud<PointXYZ> pcl {};
for (size_t i = 0; i < size; ++i) {
pcl.push_back(pcl::PointXYZ{10.0f * static_cast<float> (rand ()) / RAND_MAX,
10.0f * static_cast<float> (rand ()) / RAND_MAX,
10.0f * static_cast<float> (rand ()) / RAND_MAX});
}
#else
float x = 0;
float y = 360;
float z = 720;
PointCloud<PointXYZ> pcl {};
for (size_t i = 0; i < size; ++i) {
pcl.push_back(pcl::PointXYZ{x, y, z});
x = x + 0.1f;
y = y + 0.1f;
z = z + 0.1f;
}
#endif
PointCloud<PointXYZ>::Ptr pclPtr(new PointCloud<PointXYZ>(pcl));
std::vector<float> voxelSizes = {2.0123f, 2.3423f, 2.6723f, 3.0123f, 3.3423f, 3.6723f, 4.0123f, 4.3423f, 4.6723f};
for(const float& voxelSize: voxelSizes) {
PointCloud<PointXYZ> output;
VoxelGrid<PointXYZ> grid;
grid.setLeafSize (voxelSize, voxelSize, voxelSize);
grid.setInputCloud (pclPtr);
grid.filter (output);
PointXYZ& prev = output[0];
double dx = 0;
double dy = 0;
double dz = 0;
for (std::size_t i = 1; i < output.size(); ++i) {
const PointXYZ& curr = output[i];
dx += std::abs(curr.x - prev.x);
dy += std::abs(curr.y - prev.y);
dz += std::abs(curr.z - prev.z);
prev = curr;
}
double avgDx = dx / output.size();
double avgDy = dy / output.size();
double avgDz = dz / output.size();
std::cout << "voxelSize = " << voxelSize << ", downsampled size: " << output.size() << ", averate dx: " << avgDx
<< ", average dy: " << avgDy << ", average dz: " << avgDz<< std::endl;
}
} You are using a straight line with regular spacing between points, and voxel sizes that are a multiple of this spacing. That means that some points are exactly on the border of two voxels, and there may be voxels with only one point, leading to strange results. This is related to Aliasing. If you use slightly different voxel sizes (no exact multiples of the point-to-point spacing), the results are what you would expect. Alternatively, you can use a random cloud, which also gives you a monotonically decreasing downsampling size. |
@mvieth thank you for the response! Hm, but the algorithm should be resilient to the data issues, no? And it should be able to properly handle edge cases? If I change the way how the index is computed to compute the delta between X/Y/Z and minX/Y/Z and then multiply it by inverse_leaf_size, then the result is monotonically decreasing. Here is the patch:
It produces:
|
If my assumption that for the same input PointCloud, monotonically increasing voxel size should produce monotonically decreased downsampled PointCloud is correct then something wrong with the downsampling in VoxelGrid.
Let's take an example, the following code creates point cloud and voxelizes it with three different voxel sizes: 3.0f, 3.33f, 4.0f.
One would expect that
voxelized(3.0f).size()
>voxelized(3.33f).size()
>voxelized(4.0f).size()
, but that is not the case. (voxelized(3.0f).size()
means use VoxelGrid to voxelize with leaf size 3.0 and get the size of output). It produces the following result:Is it expected that the average difference between x/y/z of voxelized points is around voxelSize / 2, is it a mistake to expect it to be around voxelSize?
Environment:
The text was updated successfully, but these errors were encountered: