基于深度学习的点云匹配都有哪些 点云算法处理_点云


0. 点云滤波简介

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

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

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

(2)PCL 中的 filters 模块


Point Cloud Library (PCL): Module filtersdocs.pointclouds.org

基于深度学习的点云匹配都有哪些 点云算法处理_官方教程_02


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


基于深度学习的点云匹配都有哪些 点云算法处理_官方教程_03

类 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

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)


基于深度学习的点云匹配都有哪些 点云算法处理_基于深度学习的点云匹配都有哪些_04



3. 去除 outliers

(1)统计分析 StatisticalOutlierRemoval

官方教程:Removing outliers using a StatisticalOutlierRemoval filter

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

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)变少。


基于深度学习的点云匹配都有哪些 点云算法处理_pcl 使用gpu计算法向量_05


(2)半径范围 RadiusOutlierRemoval

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

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

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


基于深度学习的点云匹配都有哪些 点云算法处理_官方教程_06


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


基于深度学习的点云匹配都有哪些 点云算法处理_基于深度学习的点云匹配都有哪些_07


基于深度学习的点云匹配都有哪些 点云算法处理_官方教程_08


基于深度学习的点云匹配都有哪些 点云算法处理_字段_09



参考:

  1. PCL Documentation
  2. https://zhuanlan.zhihu.com/p/52751159