【pcl入门教程滤波系列】之VoxelGrid

VoxelGrid体素采样

  pcl库中的VoxelGrid对点云进行体素化,主要就是创建一个三维体素栅格(就是每个比较小的立方体组成的体素栅格)。在每个体素(三维立方体)里面,求取该立方体内的所有点云重心点来代表这个立方体的表示,以此达到下采样的目的。

    class pcl::ApproximateVoxelGrid<PointT>
	class pcl::VoxelGrid<PointT>
	class pcl::VoxelGird<pcl::PCLPointCloud2>

  对于体素下采样接口功能函数pcl提供了两种方式: pcl::ApproximateVoxelGridpcl::VoxelGrid。两种区别主要在于第一种是用每个体素栅格的中心点来近似该体素内的点,提升了速度,但是也损失了原始点云的局部形态精细度。

主要应用函数

    // 设置每个体素的大小, leaf_size没别为lx ly lz的长 宽 高
	inline void setLeafSize (const Eigen::Vector3f &leaf_size);
	// 不同的接口输入方式
	inline void setLeafSize (float lx, float ly, float lz);

	// 获取每个体素的大小
	inline Eigen::Vector3f getLeafSize ();

	// 设置下采样的维度,默认false, 只对XYZ进行下采样;true为对所有下采样
	inline void setDownsampleAllData (bool downsample);
	
	// 获取下采样的方式是否为XYZ还是全部下采样
	inline bool getDownsampleAllData ();
VoxelGrid / ApproximateVoxelGrid的Demo代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/approximate_voxel_grid.h>
#include <chrono>

int main(int argc, char** argv)
{
	// pcl::PCLPointCloud2::Ptr cloud(new pcl::PCLPointCloud2());
	// pcl::PCLPointCloud2::Ptr cloud_filtered(new pcl::PCLPointCloud2());
	pcl::PointCloud<pcl::PointXYZI>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZI>);
	pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZI>);

	auto startTime = std::chrono::steady_clock::now();

	// Fill in the cloud data
	pcl::PCDReader reader;
	// Replace the path below with the path where you saved your file 
	reader.read("table_scene_lms400.pcd", *cloud);

	// Create the filtering object
	// pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
	// pcl::VoxelGrid<pcl::PointXYZI> sor;
	pcl::ApproximateVoxelGrid<pcl::PointXYZI> sor;

	sor.setInputCloud(cloud);
	sor.setLeafSize(0.02f, 0.02f, 0.02f);
	// sor.setDownsampleAllData(true);
	sor.filter(*cloud_filtered);

	std::cerr << "PointCloud before filtering: " << cloud->width * cloud->height
			  << " data points ( " << pcl::getFieldsList(*cloud) << " )." << std::endl;

	std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height
			  << " data points ( " << pcl::getFieldsList(*cloud_filtered) << " )." << std::endl;


    auto endTime      = std::chrono::steady_clock::now();
    auto ellapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);

    std::cerr << "Ellapse-Time: " << ellapsedTime.count() << " milliseconds." << std::endl;

	pcl::PCDWriter writer;
	writer.write("2000line_downsampled.pcd", *cloud_filtered);

	return 0;
}

  示例性代码,比较简单就不多做解释了。下面看一看跑这个代码对比一下VoxelGrid与ApproximateVoxelGrid的实验结果:

原始点云
VoxelGrid滤波点云
ApproximateVoxelGrid滤波点云
FilterApproximateVoxelGridVoxelGrid
点云滤波前/滤波后460400/29186460400/11598
时间/milliseconds93107

  不知你是否注意到这两种方法下采样后的点云个数不一致,主要原因在于ApproximateVoxelGrid是依据每一个体素的中心点来获取点云的,并不是依赖每个体素里面是否存在点云。所以会导致两种方式的处理结果又偏差,VoxelGrid的方式更加精确但是耗时相对于ApproximateVoxelGrid更高。

小结

  点云体素下采样针对大量点云时候能够有效的保存点云空间结构同时提升算法的运行效率。基于体素的点云编码方式也是当下应用较多的一种点云处理方法。

参考

https://pointclouds.org/documentation/classpcl_1_1_approximate_voxel_grid.html
https://pcl.readthedocs.io/projects/tutorials/en/latest/voxel_grid.html#voxelgrid

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值