PCL:ApproximateVoxelGrid❤️近似体素重心下采样

文章目录

目前,网上对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 对比结果展示

PCL:ApproximateVoxelGrid❤️近似体素重心下采样
从左向右以此为原始点云、近似体素下采样点云、体素下采样点云。


相关链接:

[1] A Comparative Study of Filtering Methods for Point Clouds in Real-Time Video Streaming

通俗地理解哈希函数

PCL:VoxelGrid ❤️ 点云体素下采样

https://pointclouds.org/documentation/classpcl_1_1_approximate_voxel_grid.html

上一篇:PCL学习笔记(43)——点云最小割minCut分割算法


下一篇:Viewer.js 图片预览插件