1、PCL中的贪婪投影三角化(GreedyProjectionTriangulation)算法
该算法用于将无序点云数据转换为表面三角网络模型的表面重建算法。可以根据点云数据中的几何信息,自动构建出具有连续性和平滑性的三角网络模型。
具体步骤:
-
预处理:首先,我们对输入的点云数据进行预处理,通过各种滤波和计算法向量的方法,来提取更准确的法向量信息。这个步骤可以帮助我们获得更好的表面重建结果。
-
投影:接下来,我们将点云数据投影到一个二维网格中。这个网格是通过将点云数据的边界用一个平面包围起来生成的。对于每个点,我们根据其在边界平面上的位置进行投影,并计算其表面的朝向。
-
三角化:使用贪婪投影三角化算法,我们将点云数据转换为一个三角网格模型。算法会从每个投影网格单元中选择与其邻域最接近的点,并利用这些点之间的连接关系构建三角形。
-
可选的后处理:最后,我们可以对生成的三角网格进行一些额外处理,例如平滤波和平滑法向量等,以使其更平滑和连续。
贪婪投影三角化算法具有较高的效率和鲁棒性。它可以处理大量的点云数据,并生成高质量的表面模型。但是需要注意的是,算法对于点云数据的边界比较敏感,并且在处理具有复杂几何结构或噪声较多的点云数据时可能会产生有限的结果。因此,在实际应用中,我们可能需要根据具体情况选择其他表面重建算法来获得更好的结果。
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。
代码:
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h> // 贪婪投影三角化算法
#include <pcl/visualization/pcl_visualizer.h>
int main(){
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PCLPointCloud2 cloud_blob; // pcl::PCLPointCloud2是一种通用的点云数据表示格式,可以存储不同类型和不同结构的点云数据
pcl::io::loadPCDFile("/home/jason/file/pcl-learning/11surface表面/3无序点云的快速三角化/bun0.pcd", cloud_blob);
pcl::fromPCLPointCloud2(cloud_blob, *cloud); // 转换为特定类型的点云数据
// Normal estimation
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n; // 法线估计
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
tree->setInputCloud(cloud);
n.setInputCloud(cloud);
n.setSearchMethod(tree);
n.setKSearch(20);
n.compute(*normals);
// Concatenate the XYZ and normal fields
pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*cloud, *normals, *cloud_with_normals);
// 定义搜索树对象
pcl::search::KdTree<pcl::PointNormal>::Ptr tree2(new pcl::search::KdTree<pcl::PointNormal>);
tree2->setInputCloud(cloud_with_normals); // 点云构建搜索树
pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3; // 定义三角化对象
pcl::PolygonMesh triangles; // 用于存储最终三角化的模型
// 三角化操作
gp3.setSearchRadius(2.5);
gp3.setMu(2.5); // 表示距离参数,用于控制点云投影到三角化表面时的最近邻数量,值越大表示距离越近
gp3.setMaximumNearestNeighbors(100); // 设置点云的最大最近邻数量
gp3.setMaximumSurfaceAngle(M_PI / 4); // 设置最大表面角度,用于控制三角化结果的平滑程
gp3.setMinimumAngle(M_PI / 18); // 设置最小角度,用于控制三角化结果的细节程度
gp3.setMaximumAngle(2*M_PI/3); // 设置最大角度,用于控制三角化结果的细节程度
// 以上都是默认参数,可以不设置
gp3.setNormalConsistency(false); // 设置法向一致性,表示是否保持法向一致;如果设置为true,则生成三角化结果时会对法向进行一致性检查和调整
gp3.setInputCloud(cloud_with_normals); // 设置带有法向信息的输入点云数据
gp3.setSearchMethod(tree2); // 设置搜索方法,用于三角化操作时的点云搜索
gp3.reconstruct(triangles); // 进行三角化操作,生成三角化结果
std::vector<int> parts = gp3.getPartIDs(); // 获取三角化结果的部分ID信息
std::vector<int> states = gp3.getPointStates(); // 获取三角化结果的状态信息
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("cloud viewer"));
viewer->addPolygonMesh(triangles, "my");
viewer->addCoordinateSystem(1.0);
viewer->initCameraParameters();
while (!viewer->wasStopped()) {
viewer->spinOnce();
}
return 0;
}
![](https://img-blog.csdnimg.cn/528402b5ee6c4d95923ff36d8abb9ccd.png)
![](https://img-blog.csdnimg.cn/3dafe198da204a6badc220d92c38480b.png)
参考: