PCL学习笔记(三十四)-- 无序点云的快速三角化

一、简介

   《点云库PCL从入门到精通》P350

二、代码分析

    1)加载下采样文件,以点云对象指针的形式进行保存:

  // Load input file into a PointCloud<T> with an appropriate type
  //将一个xyz点类型的pcd打开并存储到对象PointCloud中
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);  //定义点云对象指针用于保存点云文件
  pcl::PCLPointCloud2::Ptr cloud_blob(new pcl::PCLPointCloud2);                    //定义点云对象指针用于加载下采样后的点云
  pcl::io::loadPCDFile ("table_scene_lms400_downsampled.pcd", *cloud_blob);        //打开下采样文件
  pcl::fromPCLPointCloud2(*cloud_blob, *cloud);                                    //将下采样文件作为模板进行保存
  //* the data should be available in cloud

    2)构建法线估计的对象:

  // 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>);  //定义kd tree指针
  tree->setInputCloud (cloud);                                                            //用点云来构建树
  n.setInputCloud (cloud);                                                                //为法线估计对象输入点云
  n.setSearchMethod (tree);                                                               //设置法线估计对象的搜索方法
  n.setKSearch (20);                                                                      //设置k搜索的k值为20
  n.compute (*normals);                                                                   //估计法线存储结果到normals中
  //* normals should not contain the point normals + surface curvatures

    3)将点云与发现进行字段拼接,构成一个有向点云,在有向点云中构建kd tree:

  // 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);                                    //将点云与法线进行字段连接,保存至有向点云对象中
  //* cloud_with_normals = cloud + normals

  // Create search tree*
  pcl::search::KdTree<pcl::PointNormal>::Ptr tree2 (new pcl::search::KdTree<pcl::PointNormal>);      //构建一个kd tree对象
  tree2->setInputCloud (cloud_with_normals);                                                         //将kd tree的输入点云设置为有向点云对象

    4)初始化三角化对象,并设置相应的参数:

  // Initialize objects
  pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;                                          //初始化一个贪婪三角化对象
  pcl::PolygonMesh triangles;                                                                        //存储最终三角化的网络模型

  // Set the maximum distance between connected points (maximum edge length)
  gp3.setSearchRadius (0.025);                                                                       //设置连接点之间的最大距离(即为三角形最大边长)

  // Set typical values for the parameters
  gp3.setMu (2.5);                                                                                   //设置样本点搜索其邻近点的最远距离为2.5,为了适应点云密度的变化
  gp3.setMaximumNearestNeighbors (100);                                                              //设置样本点可搜索的邻域个数为100
  gp3.setMaximumSurfaceAngle(M_PI/4); // 45 degrees                                                  //设置某点法线方向偏离样本点法线方向的最大角度为45度
  gp3.setMinimumAngle(M_PI/18); // 10 degrees                                                        //设置三角形化后得到的三角形内角最小角度为10度
  gp3.setMaximumAngle(2*M_PI/3); // 120 degrees                                                      //设置三角形化后得到的三角形内角最大角度为120度
  gp3.setNormalConsistency(false);                                                                   //设置该参数保证法线朝向一致

  // Get result
  gp3.setInputCloud (cloud_with_normals);                                                            //设置输入点云为有向点云
  gp3.setSearchMethod (tree2);                                                                       //设置搜索方法
  gp3.reconstruct (triangles);                                                                       //重建提取三角化

    5)整体代码

#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>
#include <boost/thread/thread.hpp>

int main(int argc, char** argv)
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);						//智能指针加载点云数据
	pcl::PCLPointCloud2::Ptr cloud_blob(new pcl::PCLPointCloud2);
	pcl::io::loadPCDFile("table_scene_lms400_downsampled.pcd", *cloud_blob);
	pcl::fromPCLPointCloud2(*cloud_blob, *cloud);

	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>);				//智能指针存储kd tree
	tree->setInputCloud(cloud);
	n.setInputCloud(cloud);
	n.setSearchMethod(tree);
	n.setKSearch(20);
	n.compute(*normals);																				//执行法线估计

	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(0.025);																			//设置两点之间的最近距离

	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);																	//是否考虑法线

	gp3.setInputCloud(cloud_with_normals);
	gp3.setSearchMethod(tree2);
	gp3.reconstruct(triangles);																			//利用三角形进行重构

	std::vector<int>parts = gp3.getPartIDs();															//贪婪三角形可视化
	std::vector<int>states = gp3.getPointStates();
	boost::shared_ptr<pcl::visualization::PCLVisualizer> 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));
	}
	return(0);
}

三、编译结果

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值