文章目录
目前,网上对PCL中的ApproximateVoxelGrid
下采样方法绝大多数描述为 “体素中心下采样”
事实并非如此!!!
1 原理
ApproximateVoxelGrid
近似体素滤波企图以 更快的速度 实现与VoxelGrid
体素滤波相同的下采样,它通过 散列函数(Hashing Function)快速逼近质心,而不是精细确定质心并对点云进行下采样。采样结果是近似逼近的体素质心,并不是体素中心。
2 代码实现
代码:
#include <pcl/io/pcd_io.h>
#include <pcl/filters/approximate_voxel_grid.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/console/time.h>
using namespace std;
int main()
{
//--------------------------------- 加载点云 ---------------------------------
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); //待滤波点云
if (pcl::io::loadPCDFile("happy buddha.pcd", *cloud) < 0)
{
PCL_ERROR("\a点云文件不存在!\n");
system("pause");
return -1;
}
cout << "->加载点云的点数为:" << cloud->points.size() << endl;
//============================================================================
//----------------------------- 近似体素重心下采样 -----------------------------
pcl::console::TicToc time;
time.tic();
cout << "->正在进行近似体素重心下采样..." << endl;
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_sub(new pcl::PointCloud<pcl::PointXYZ>); //滤波后点云
pcl::ApproximateVoxelGrid<pcl::PointXYZ> avg; //创建滤波器对象
avg.setInputCloud(cloud); //设置待滤波点云
avg.setLeafSize(0.002, 0.002, 0.002); //设置体素边长
avg.setDownsampleAllData(false); //如果只有XYZ字段,则设置为false,如果对所有字段,如intensity,都进行下采样,则设置为true
avg.filter(*cloud_sub); //执行下采样,保存结果于cloud_sub
cout << "->近似体素下采样用时:" << time.toc() / 1000 << " s" << endl;
//============================================================================
//------------------------------- 保存滤波点云 --------------------------------
cout << "->正在保存滤波点云..." << endl;
if (!cloud_sub->empty())
{
pcl::io::savePCDFileBinary("ApproximateVoxelGrid.pcd", *cloud_sub);
cout << "->下采样点云的点数为" << cloud_sub->points.size() << endl;
}
else
{
PCL_ERROR("\a下采样点云为空!\n");
system("pause");
return -1;
}
//============================================================================
//------------------------- 下采样前后对比可视化(选) --------------------------
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("下采样前后对比"));
///原始点云
int v1(0);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1); //设置第一个视口在X轴、Y轴的最小值、最大值,取值在0-1之间
viewer->setBackgroundColor(0, 0, 0, v1); //设置背景颜色,0-1,默认黑色(0,0,0)
viewer->addText("original_Pt", 10, 10, "v1_text", v1);
viewer->addPointCloud<pcl::PointXYZ>(cloud, "original", v1);
///半径滤波后点云
int v2(0);
viewer->createViewPort(0.5, 0.0, 1.0, 1.0, v2);
viewer->setBackgroundColor(0.3, 0.3, 0.3, v2);
viewer->addText("filtered_Pt", 10, 10, "v2_text", v2);
viewer->addPointCloud<pcl::PointXYZ>(cloud_sub, "sub", v2);
///设置相关属性
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "original", v1);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "original", v1);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "sub", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "sub", v2);
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
//============================================================================
return 0;
}
输出结果:
->加载点云的点数为:543652
->正在进行近似体素重心下采样...
->近似体素下采样用时:0.916 s
->正在保存滤波点云...
->下采样点云的点数为54889
体素下采样输出结果:
->加载了 543652 个数据点
->正在进行体素下采样...
->体素下采样用时:2.915 s
->下采样点云的点数为:18072
对比发现,同一规格体素下,近似体素下采样 比 体素下采样 获取的下采样点数多,且耗时短。
3 对比结果展示
从左向右以此为原始点云、近似体素下采样点云、体素下采样点云。
相关链接:
[1] A Comparative Study of Filtering Methods for Point Clouds in Real-Time Video Streaming
https://pointclouds.org/documentation/classpcl_1_1_approximate_voxel_grid.html