pcl 使用gpu计算法向量_【PCL笔记】Filtering 点云滤波

a3463c54fb7126bdf8247e79fff38502.png

0. 点云滤波简介

(1)哪些情况需要滤波?

  • 点云数据密度不规则需要平滑
  • 遮挡等问题造成离群点(outliers)需要去除
  • 大量数据需要进行下采样( downsample )
  • 噪声数据需要去除(noise remove)

点云滤波通常为点云预处理的第一步,只有将噪声点、离群点、孔洞、数据压缩等做相关处理后,才能更好地进行特征提取、配准、曲面重建、可视化等应用。

(2)PCL 中的 filters 模块

Point Cloud Library (PCL): Module filters​docs.pointclouds.org
cdc509f94b8853f41c155d2aae0b0c32.png

Filters 模块包含32个类和5个函数,其依赖于 pcl::common, pcl::sample_consencus, pcl::search, pcl::kdtree, pcl::octree模块。

85b26d73c13e37a1ee4d646751c25762.png
类 Filter 继承关系
  • class pcl::ApproximateVoxelGrid< PointT >
  • class pcl::BilateralFilter< PointT >
  • class pcl::BoxClipper3D< PointT >
  • class pcl::Clipper3D< PointT >
  • class pcl::ConditionalRemoval< PointT >
  • class pcl::filters::Convolution< PointIn, PointOut >
  • class pcl::filters::ConvolvingKernel< PointInT, PointOutT >
  • class pcl::filters::GaussianKernel< PointInT, PointOutT >
  • class pcl::filters::GaussianKernelRGB< PointInT, PointOutT >
  • class pcl::CropBox< PointT >
  • class pcl::CropBox< pcl::PCLPointCloud2 >
  • class pcl::CropHull< PointT >
  • class pcl::ExtractIndices< PointT >
  • class pcl::ExtractIndices< pcl::PCLPointCloud2 >
  • class pcl::Filter< PointT >
  • class pcl::Filter< pcl::PCLPointCloud2 >
  • class pcl::FilterIndices< PointT >
  • class pcl::FilterIndices< pcl::PCLPointCloud2 >
  • class pcl::FrustumCulling< PointT >
  • class pcl::GridMinimum< PointT >
  • class pcl::LocalMaximum< PointT >
  • class pcl::MedianFilter< PointT >
  • class pcl::NormalRefinement< NormalT >
  • class pcl::NormalSpaceSampling< PointT, NormalT >
  • class pcl::PlaneClipper3D< PointT >
  • class pcl::ProjectInliers< PointT >
  • class pcl::ProjectInliers< pcl::PCLPointCloud2 >
  • class pcl::RandomSample< PointT >
  • class pcl::RandomSample< pcl::PCLPointCloud2 >
  • class pcl::SamplingSurfaceNormal< PointT >
  • class pcl::ShadowPoints< PointT, NormalT >
  • class pcl::VoxelGridOcclusionEstimation< PointT >

1. PassThrough 直通滤波

官方教程:Filtering a PointCloud using a PassThrough filter

  • class pcl::PassThrough< PointT >
  • class pcl::PassThrough< pcl::PCLPointCloud2 >
PassThrough passes points in a cloud based on constraints for one particular field of the point type.
Iterates through the entire input once, automatically filtering non-finite points and the points outside the interval specified by setFilterLimits(), which applies only to the field specified by setFilterFieldName().
  pcl::PassThrough<pcl::PointXYZ> pass;    // 创建直通滤波器对象
  pass.setInputCloud (cloud);              // 输入点云
  pass.setFilterFieldName ("z");           // 设置过滤字段
  pass.setFilterLimits (0.0, 1.0);         // 设置范围
  //pass.setFilterLimitsNegative (true);   // 设置字段范围内的是保留(false)还是过滤掉(true)
  pass.filter (*cloud_filtered);           // 执行滤波,并存储结果

2. VoxelGrid 点云下采样

官方教程:Downsampling a PointCloud using a VoxelGrid filter

  • class pcl::ApproximateVoxelGrid< PointT >
  • class pcl::VoxelGrid< PointT >
  • class pcl::VoxelGrid< pcl::PCLPointCloud2 >
The VoxelGridclass creates a 3D voxel grid (think about a voxel grid as a set of tiny 3D boxes in space) over the input point cloud data. Then, in each voxel (i.e., 3D box), all the points present will be approximated (i.e., downsampled) with their centroid. This approach is a bit slower than approximating them with the center of the voxel, but it represents the underlying surface more accurately.

VoxelGrid类根据 输入的点云数据创建一个三维体素栅格,然后将每个体素内所有的点都用该体素内的点集的重心(centroid)来近似;ApproximateVoxelGrid类与VoxelGrid类基本相同,唯一不同在于其利用每一个体素的中心(center)来近似该体素内的点,相比于 VoxelGrid,计算速度稍快,但也损失了原始点云局部形态的精细度。

// 创建对象
pcl::VoxelGrid<pcl::PointXYZ> voxel;
// 输入点云
voxel.setInputCloud (cloud);
// 设置体素大小
voxel.setLeafSize (0.01f, 0.01f, 0.01f);
// 输出点云
voxel.filter (*cloud_filtered);

关键成员函数:

// 通过向量设置体素栅格 leaf_size
void setLeafSize (const Eigen::Vector4f &leaf_size) 
// 通过 lx, ly, lz 分别设置体素栅格在 XYZ 3个方向上的尺寸
void setLeafSize (float lx, float ly, float lz)
// 设置是否对全部字段进行下采样
// 若需要在全部字段(包括颜色、强度等)下采样则设置参数 downsample 为 True 
// 仅对 XYZ 字段下采样则设置为 False 
void setDownsampleAllData ( bool downsample)

e760062dff92ad29e8461992864d0958.png

3. 去除 outliers

(1)统计分析 StatisticalOutlierRemoval

官方教程:Removing outliers using a StatisticalOutlierRemoval filter

  • class pcl::StatisticalOutlierRemoval< PointT >
  • class pcl::StatisticalOutlierRemoval< pcl::PCLPointCloud2 >
Some of these irregularities can be solved by performing a statistical analysis on each point's neighborhood, and trimming those which do not meet a certain criteria.
Our sparse outlier removal is based on the computation of the distribution of point to neighbors distances in the input dataset.
For each point, we compute the mean distance from it to all its neighbors.
By assuming that the resulted distribution is Gaussian with a mean and a standard deviation, all points whose mean distances are outside an interval defined by the global distances mean and standard deviation can be considered as outliers and trimmed from the dataset.

对每个点的邻域进行统计分析,计算所有邻点的平均距离,假如得到的分布为高斯分布,就可以得到均值和标准差,平均距离在区间

+ std_mul *
之外的点视为离群点,std_mul为表示标准差倍数的阈值。
  pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
  sor.setInputCloud (cloud);
  sor.setMeanK (50);               // 设置临近点个数
  sor.setStddevMulThresh (1.0);    // 设置阈值,判断是否为离群点
  sor.filter (*cloud_filtered);


结果:右图中红色与绿色分别表示滤波前后 mean k-nearest neighbor distances,可见离群点(outliers)变少。

57ad9f7e11c1e96675451a255a5e4065.png

(2)半径范围 RadiusOutlierRemoval

官方教程:Removing outliers using a Conditional or RadiusOutlier removal

  • class pcl::RadiusOutlierRemoval< PointT >
  • class pcl::RadiusOutlierRemoval< pcl::PCLPointCloud2 >

通过指定空间半径范围内的邻点数量来判定是否为离群点,如下图所示,若设定搜索半径为 d,最少的邻点数量为 1,则黄点将被视为离群点,若最少的邻点数量为2,则黄点和绿点都被视为离群点。

cbbe560cc88e2c0c0c3be8ec038bf7fd.png
pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;
outrem.setInputCloud(cloud);
outrem.setRadiusSearch(0.8);          // 设置搜索半径
outrem.setMinNeighborsInRadius (2);   // 设置最少的邻点数量
outrem.filter (*cloud_filtered);

4. 通过点云索引提取点云子集

官方教程:Extracting indices from a PointCloud

  • class pcl::ExtractIndices< PointT >
  • class pcl::ExtractIndices< pcl::PCLPointCloud2 >
extract a subset of points from a point cloud based on the indices output by a segmentation algorithm.
// 下采样
pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
sor.setInputCloud (cloud_blob);
sor.setLeafSize (0.01f, 0.01f, 0.01f);
sor.filter (*cloud_filtered_blob);

// 参数化分割
pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ());
pcl::PointIndices::Ptr inliers (new pcl::PointIndices ());
// Create the segmentation object
pcl::SACSegmentation<pcl::PointXYZ> seg;
// Optional
seg.setOptimizeCoefficients (true);
// Mandatory
seg.setModelType (pcl::SACMODEL_PLANE);
seg.setMethodType (pcl::SAC_RANSAC);
seg.setMaxIterations (1000);
seg.setDistanceThreshold (0.01);

// 提取索引
pcl::ExtractIndices<pcl::PointXYZ> extract;
// Extract the inliers
extract.setInputCloud (cloud_filtered);
extract.setIndices (inliers);       // 设置分割后的内点为需要提取的点集
extract.setNegative (false);        // 设置提取内点
extract.filter (*cloud_p);          // 提取并保存至 cloud_p

e79a264728bd88dbf9a2187f893f99cd.png

dd6030ddd4741a7f6d615c49a08531a6.png

c70ce875baf5d56bba4be53cdf8ca3c0.png

参考:

  1. PCL Documentation
  2. https://zhuanlan.zhihu.com/p/52751159
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值