PCL学习:无序点云的快速三角化

1. 贪婪投影三角化算法

        将三维点通过法线投影到某一平面,然后对投影得到的点云作平面内的三角化,从而得到各点的连接关系。在平面区域三角化的过程中用到了基于 Delaunay 的 空间区域增长算法,该方法通过选取一个样本三角片作为初始曲面,不断扩张曲面边界,最后形成一张完整的三角网格曲面。最后根据投影点云的连接关系确定各原始三维点间的拓扑连接,所得三角格网即为重建得到的曲面模型。
        贪婪投影三角化算法是一种对原始点云进行快速三角化的算法。该算法假设曲面光滑,点云密度变化均匀,不能在三角化的同时对曲面进行平滑和孔洞修复 。

        使用贪婪投影三角化算法对有向点云进行三角化,具体方法是先将有向点云投影到某一局部二维坐标平面内,再在坐标平面内进行平面内的三角化,再根据平面内三位点的拓扑连接关系获得一个三角网格曲面模型。贪婪投影三角化算法原理是处理一系列可以使网格“生长扩大”的点(边缘点),延伸这些点直到所有符合几何正确性和拓扑正确性的点都被连上。该算法的优点是可以处理来自一个或者多个扫描仪扫描得到并且有多个连接处的散乱点云。但该算法也有一定的局限性,它更适用于采样点云来自于表面连续光滑的曲面并且点云密度变化比较均匀的情况。

        该算法中的三角化过程是局部进行的,首先沿着一点的法线将该点投影到局部二维坐标平面内并连接其他悬空点,然后在进行下一点。

2. class pcl: :GreedyProjectionTriangulation< PointlnT>

类 GreedyProjectionTriangulation 实现了将三维点投影到某一局部二维坐标平面的贪婪三角化算法,该算法需要点云平滑,并且密度变化连续。

关键成员函数:

  • SetMaximumNearestNeighbors(unsigned)和SetMu(double):这两个函数的作用是控制搜索邻域大小。前者定义了可搜索的邻域个数,后者规定了被样本点搜索其邻近点的最远距离,(是为了适应点云密度的变化),特征值一般是50-100和2.5-3(或者1.5每栅格);
  • SetSearchRadius(double): 该函数设置了三角化后得到的每个三角形的最大可能边长;
  • SetMinimumAngle(double)和SetMaximumAngle(double) :这两个函数是三角化后每个三角形的最大角和最小角。两者至少要符合一个。典型值分别是10和120度(弧度);
  • SetMaximumSurfaceAgle(double)和SetNormalConsistency(bool):这两个函数是为了处理边缘或者角很尖锐以及一个表面的两边非常靠近的情况。为了处理这些特殊情况,函数SetMaximumSurfaceAgle(double)规定如果某点法线方向的偏离超过指定角度(注:大多数表面法线估计方法可以估计出连续变化的表面法线方向,即使在尖锐的边缘条件下),该点就不连接到样本点上。该角度是通过计算法向线段(忽略法线方向)之间的角度;
  • 函数SetNormalConsistency(bool)保证法线朝向,如果法线方向一致性标识没有设定,就不能保证估计出的法线都可以始终朝向一致。第一个函数特征值为45度(弧度)、第二个函数缺省值为false。

3. 测试示例

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int
main (int argc, char** argv)
{
  // Load input file into a PointCloud with an appropriate type
  pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
  pcl::PCLPointCloud2 cloud_blob;
  pcl::io::loadPCDFile ("..\\..\\source\\table_scene_lms400_downsampled.pcd", cloud_blob);
  pcl::fromPCLPointCloud2(cloud_blob, *cloud);
  //* the data should be available in cloud

  // Normal estimation*
  pcl::NormalEstimation n;//设置法线估计对象
  pcl::PointCloud::Ptr normals (new pcl::PointCloud);//存储估计的法线
  pcl::search::KdTree::Ptr tree (new pcl::search::KdTree);//定义kd树指针
  tree->setInputCloud (cloud);//用cloud构造tree对象
  n.setInputCloud (cloud);//为法线估计对象设置输入点云
  n.setSearchMethod (tree);//设置搜索方法
  n.setKSearch (20);//设置k邻域搜素的搜索范围
  n.compute (*normals);//估计法线
  //* normals should not contain the point normals + surface curvatures

  // Concatenate the XYZ and normal fields*
  pcl::PointCloud::Ptr cloud_with_normals (new pcl::PointCloud);//
  pcl::concatenateFields (*cloud, *normals, *cloud_with_normals);//连接字段,cloud_with_normals存储有向点云
  //* cloud_with_normals = cloud + normals

  // Create search tree*
  pcl::search::KdTree::Ptr tree2 (new pcl::search::KdTree);//定义搜索树对象
  tree2->setInputCloud (cloud_with_normals);//利用有向点云构造tree

  // Initialize objects
  pcl::GreedyProjectionTriangulation gp3;//定义三角化对象
  pcl::PolygonMesh triangles;//存储最终三角化的网络模型

  // Set the maximum distance between connected points (maximum edge length)
  gp3.setSearchRadius (0.025);         //设置搜索半径radius,来确定三角化时k一邻近的球半径。

  // Set typical values for the parameters
  gp3.setMu (2.5);                     //设置样本点到最近邻域距离的乘积系数 mu 来获得每个样本点的最大搜索距离,这样使得算法自适应点云密度的变化
  gp3.setMaximumNearestNeighbors (100);//设置样本点最多可以搜索的邻域数目100 。
  gp3.setMaximumSurfaceAngle(M_PI/4);  //45 degrees,设置连接时的最大角度 eps_angle ,当某点法线相对于采样点的法线偏离角度超过该最大角度时,连接时就不考虑该点。
  gp3.setMinimumAngle(M_PI/18);        //10 degrees,设置三角化后三角形的最小角,参数 minimum_angle 为最小角的值。
  gp3.setMaximumAngle(2*M_PI/3);       //120 degrees,设置三角化后三角形的最大角,参数 maximum_angle 为最大角的值。
  gp3.setNormalConsistency(false);     //设置一个标志 consistent ,来保证法线朝向一致,如果设置为 true 则会使得算法保持法线方向一致,如果为 false 算法则不会进行法线一致性检查。

  // Get result
  gp3.setInputCloud (cloud_with_normals);//设置输入点云为有向点云
  gp3.setSearchMethod (tree2);           //设置搜索方式tree2
  gp3.reconstruct (triangles);           //重建提取三角化
 // std::cout << triangles;
  // Additional vertex information
  std::vector parts = gp3.getPartIDs();//获得重建后每点的 ID, Parts 从 0 开始编号, a-1 表示未连接的点。
  /*
  获得重建后每点的状态,取值为 FREE 、 FRINGE 、 BOUNDARY 、 COMPLETED 、 NONE 常量,
  其中 NONE 表示未定义, 
  FREE 表示该点没有在 三 角化后的拓扑内,为自由点, 
  COMPLETED 表示该点在三角化后的拓扑内,并且邻域都有拓扑点,
  BOUNDARY 表示该点在三角化后的拓扑边缘, 
  FRINGE 表示该点在 三 角化后的拓扑内,其连接会产生重叠边。
  */
  std::vector states = gp3.getPointStates();

  boost::shared_ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
  viewer->setBackgroundColor (0, 0, 0);
  viewer->addPolygonMesh(triangles,"my");
 
  viewer->addCoordinateSystem (1.0);
  viewer->initCameraParameters ();
   // 主循环
  while (!viewer->wasStopped ())
  {
    viewer->spinOnce (100);
    boost::this_thread::sleep (boost::posix_time::microseconds (100000));
  }
  // Finish
  return (0);
}

 .\greedy_projection.exe

PCL学习:无序点云的快速三角化_第1张图片 放大之后可见是由许多三角形网格拼成的模型:

PCL学习:无序点云的快速三角化_第2张图片

你可能感兴趣的:(PCL,点云库PCL从入门到精通)