Reputation: 11
Now I work in Point Cloud, in my case, my Point Cloud is noisy in outlier, I want to clear the noise, so I go with the Radius outlier filter in PCL. The execution time of small clouds is good, but the time will increase as the point cloud size increases.
pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;
outrem.setInputCloud(box_cloud);
outrem.setRadiusSearch(0.007);
outrem.setMinNeighborsInRadius (150);
outrem.setKeepOrganized(false);
// apply filter
outrem.filter (*box_cloud);**
In my case, it takes around 15 seconds.
Looking for a solution to reduce this time.
Upvotes: 1
Views: 1728
Reputation: 11
I hope it is not too late for this answer.
Another possible approach is to split the point cloud into chunks and process them asynchronously using modern C++ features.
First, a function is created to simplify the reading of the code.
pcl::PointCloud<pcl::PointXYZ>::Ptr filterAsyncChunk(pcl::PointCloud<pcl::PointXYZ>::Ptr input_chunk,
double radius,int min_neighbors) {
pcl::PointCloud<pcl::PointXYZ>::Ptr output_chunk(new pcl::PointCloud<pcl::PointXYZ>);
pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;
outrem.setInputCloud(input_chunk);
outrem.setRadiusSearch(radius);
outrem.setMinNeighborsInRadius(min_neighbors);
outrem.filter(*output_chunk);
return output_chunk;
}
Using std::async and std::future, the chunks created are processed asynchronously.
void parallelRadiusOutlierRemovalAsync(
pcl::PointCloud<pcl::PointXYZ>::Ptr input_cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr output_cloud,
double radius, int min_neighbors, int num_threads) {
int chunk_size = input_cloud->points.size() / num_threads;
std::vector<std::future<pcl::PointCloud<pcl::PointXYZ>::Ptr>> futures;
// Divide the input cloud into chunks and process each with std::async
for (int i = 0; i < num_threads; ++i) {
pcl::PointCloud<pcl::PointXYZ>::Ptr chunk(new pcl::PointCloud<pcl::PointXYZ>);
int start_idx = i * chunk_size;
int end_idx = (i == num_threads - 1) ? input_cloud->points.size()
: (i + 1) * chunk_size;
chunk->points.insert(chunk->points.end(),
input_cloud->points.begin() + start_idx,
input_cloud->points.begin() + end_idx);
futures.emplace_back(std::async(std::launch::async, filterAsyncChunk, chunk,
radius, min_neighbors));
}
// Wait for all futures and combine results
for (auto &fut : futures) {
*output_cloud += *fut.get();
}
}
To use it, the function call would be very simple. The point cloud shall be divided into as many chunks as the number of threads to be used.
...
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>());
const double search_radius{0.2};
const int min_neighbours{10};
const int num_threads{10}; // If you want to use all available threads, use: 'std::thread::hardware_concurrency()'
parallelRadiusOutlierRemovalAsync(input_cloud, cloud_filtered, search_radius, min_neighbours, num_threads);
I hope this can help.
Marco.
Upvotes: 1
Reputation: 2170
Iterates through the entire input once, and for each point, retrieves the number of neighbors within a certain radius.
So the runtime depends on the number of points in the cloud, and the search radius (the larger the radius, the slower the tree queries will be).
Possible approaches:
intensity < I
using pcl::PassThrough.pcl::CropBox
may be used for this.Upvotes: 1