PCL学习:基于多项式平滑点云及法线估计的曲面重建

一. 基于多项式平滑点云及法线估计的曲面重建

本小节介绍基于移动最小二乘法(MLS)的法线估计、点云平滑和数据重采样。有时,测量较小的对象时会产生一些误差,这些误差所造成的不规则数据如果直接拿来曲面重建的话会使重建的曲面不光滑或者有漏洞。这些不规则很难用统计分析消除,所以为了建立完整的模型必须对表面进行平滑处理和漏洞修复。在不能进行额外扫描的情况下,我们可以通过对数据重采样来解决这一问题,重采样算法通过对周围数据点进行高阶多项式插值来重建表面缺少的部分。此外,由多个扫描点扫描结果配准后得到的数据直接拿来曲面重建的话会产生“双墙”等人造伪数据,即某块区域会出现重叠的两个曲面。重采样算法也可以对这个问题进行处理。

_images/resampling_1.jpg
图1 法线估计结果

_images/resampling_2.jpg

图2 曲率图

如图1左侧,是一个由两组点云数据配后得到的数据集的表面法线估计的结果,由于配准造成的误差,法线有噪声,即使在同一平面上的点集,其法线方向不严格一致;右侧则是同一数据集经过点云平滑后再进行法线估计所得到的结果,明显比左图准确一致的多。为了对重采样前后曲率特征进行量化衡量,我们绘制出了数据集中每点的曲率,得到图2,与上图可视化结果一致,平滑处理前的曲率特征方差很大,而平滑后的则方差较小。

二、class pcl: : MovingLeastSquares< PointlnT, PointOutT>
类 MovingLeastSquares 实现了基于移动最小二乘算法的点云平滑处理、数据重采样,并且可以计算优化的估计法线,其输入是点云数据,输出为经过用户设定参数对应的处理之后得到的平滑重采样点云。
类 MovingLeastSquares 关键成员函数 :

  • void setPolynomialOrder(int order)

设置使用多项式拟合进行运算时所用的阶数 order .

  • void se tPolynomia!Fit( bool polynomial_fit)

设置在进行估计法线时是否使用多项式拟合进行逼近,还是仅通过切线估计得到, polynomial_ fit 参数为 true 则设置为是 。

  • void setComputeNormals ( bool compute_normals)

设置是否计算并存储点云对应的法线,参数 compute_ normals 为 true 则设置为是。

  • void setSearchRadius(double radius)

设置搜索半径 radius ,确定多项式拟合时所用的邻域点进行 k 近邻搜索时所用的半径。

  • void setSqrGaussParam(double sqr_gauss_param)

设置近邻高斯权重系数 sqr_ gauss_ param , 一般设置成搜索半径的平方时效果最好。

  • void setU psamplingMethod( U psamplingMethod method)

设置上采样算法 method ,共提供 4 种方式:

  1. NONE :不进行上采样,直接将原始点投影到由最小二乘拟合出的曲面,得到采样后的点。
  2. SAMPLE_LOCAL_ PLANE :按照设置好的参数上采样半径( upsampling_radius)和参数上采样迭代步数( upsampling_ step ),在定义出的平面局部邻域内画圆,再将圆投影到拟合曲面上,再进行离散采样,得到采样后的点。
  3. RANDOM_UNIFORM_DENSITY :在定义出的平面局部邻域内,按设置好的点密度均匀取点,再将其投影到拟合曲面上,得到采样点。
  4. VOXEL_GRID_DILATION :通过设置参数体素大小( voxel_size)将原始点云所在空间进行体素化处理,再通过设置参数体素膨胀次数( dilation _ iteration _num)对体素进行膨胀,膨胀过程中将没有点云的栅格体素中也填充上点云,最后得到采样后的点。
  • void setUpsamplingRations (double radius)

设置上采样半径 radius ,用于 SAMPLE_LOCAL_PLANE o

  • void setUpsamplingStepSize (double step_size)

设置上采样迭代次数 step_size ,用于 SAMPLE_LOCAL_PLANE 。

  • void setPointDens ity(int desired」num_ points_in_radius)

设置点的采样密度 desired_ num_ points_ in_ radius ,用于 RAN以)M_ UNIFORM_ENSITY 。

  • void setDilationVoxelSize (float voxel size)

设置体素的大小 voxel_size ,用于 VOXEL_GRID_DILATIO. 、。

  • void setDilationlterations (int iterations)

设置体素膨胀次数 iterations ,用于 VOXEL_GRID_DILATION 。

  • void process (PointCloudOut 8>ι output)

对所有输人点 云进行基于最小二乘法算法的曲面重建,输出结果为曲面模型并存储在 output 中 。

  • virtual void process ( pcl : : PointCloud< PointOutT> &output)

处理输入的点云 ,并将输出结果存储在 output 中, output 点类型与模板类参数PointOutT 对应。

三、测试示例

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/surface/mls.h>

int
main (int argc, char** argv)
{// 将一个适当类型的输入文件加载到对象PointCloud中
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ> ());
  // 加载bun0.pcd文件,加载的文件在 PCL的测试数据中是存在的 
  pcl::io::loadPCDFile ("..\\..\\source\\bun0.pcd", *cloud);
  // 创建一个KD树
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
  // 输出文件中有PointNormal类型,用来存储移动最小二乘法算出的法线
  pcl::PointCloud<pcl::PointNormal> mls_points;
  // 定义对象 (第二种定义类型是为了存储法线, 即使用不到也需要定义出来)
  pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointNormal> mls;
  mls.setComputeNormals (true);

  //设置参数
  mls.setInputCloud (cloud);  //设置输入点云
  mls.setPolynomialFit (true);//设置在最小二乘计算中需要法线估计
  mls.setSearchMethod (tree); 
  mls.setSearchRadius (0.03); //设置搜索半径,确定多项式拟合时所用的邻域点进行k近邻搜索时所用的半径
  // 曲面重建
  mls.process (mls_points);

  // 保存结果
  pcl::io::savePCDFile ("bun0-mls.pcd", mls_points);

  return 0;
}

猜你喜欢

转载自blog.csdn.net/zfjBIT/article/details/95327306