点云数据曲面重建(三角化)

1、介绍

     曲面重建算法多种多样,例如泊松曲面重建,基于Delaunay生长法的三维点云曲面重,贪婪投影三角化算法,基于B样条曲线的曲面重建;在此我学习一下无序点云三角化算法,原理为将摄像机扫描的三维点云进行曲面重建,重建后曲面由三角形构成。

2、原理

      在PCL库中,使用算法依托于有序点云三角化,将有序点云投影到局部二维坐标平面系内,链接个顶点的关系,在坐标平面内三角化,最后根据拓扑关系建立三角形曲面网格;在平面区域三角化的过程中用到了基于 Delaunay 的 空间区域增长算法,该方法通过选取一个样本三角片作为初始曲面,不断扩张曲面边界,最后形成一张完整的三角网格曲面。最后根据投影点云的连接关系确定各原始三维点间的拓扑连接,所得三角格网即为重建得到的曲面模型。

      使用方法:将有向点云投影到某一局部二维坐标平面内,再在坐标平面内进行平面内的三角化,再根据平面内三位点的拓扑连接关系获得一个三角网格曲面模型。

      算法优点:可以处理多个扫描出来的散乱点云;算法缺点:局限性,只能处理表面光滑且点云密度分布均匀的情况。

3、步骤

     步骤一:如果数据过大,可使用体素滤波算法对数据下采样

     步骤二:将无序点云转化为有序点云,在PCL库中,数据形式可建立为kdtree或者八叉树,是的点云数据有一定的结构。

     步骤三:借助PCL使用贪婪投影三角化方法生成曲面三角形集合,其中每一个三角形包括三个点和法向量,至此,曲面建设完成。

4、展示

5、代码:

    //体素滤波 下采样
	pcl::VoxelGrid<pcl::PointXYZ> sor;
	sor.setInputCloud(cloud);
	sor.setLeafSize(2.0f,2.0f, 2.0f);
	sor.filter(*cloud_new);
	
	//法线估计对象
	pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;
	//存储估计的法线
	pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
	//定义kd树指针
	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
	tree->setInputCloud(cloud_new);
	n.setInputCloud(cloud_new);
	n.setSearchMethod(tree);
	n.setKSearch(10);
	//估计法线存储到其中
	n.compute(*normals);//Concatenate the XYZ and normal fields*
	pcl::PointCloud<pcl::PointNormal>::Ptr cloud_width_normals(new pcl::PointCloud<pcl::PointNormal>);
	//链接字段
	pcl::concatenateFields(*cloud_new, *normals, *cloud_width_normals);
	//定义搜索树对象
	pcl::search::KdTree<pcl::PointNormal>::Ptr tree2(new pcl::search::KdTree<pcl::PointNormal>);
	//点云构建搜索树
	tree2->setInputCloud(cloud_width_normals);

	//定义三角化对象
	pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;
	//存储最终三角化的网络模型
	pcl::PolygonMesh triangles;//设置连接点之间的最大距离,(即是三角形最大边长)
	gp3.setSearchRadius(5.0f);
	//设置各种参数值
	gp3.setMu(3.5f);
	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_width_normals);
	gp3.setSearchMethod(tree2);

	//执行重构,结果保存在triangles中
	gp3.reconstruct(triangles);
	std::string sav = "saved mesh in:";
	sav += output_dir;
	pcl::console::print_info(sav.c_str());
	std::cout << std::endl;

	
	pcl::PointCloud<pcl::PointNormal> tempCloud;
	pcl::fromPCLPointCloud2(triangles.cloud, tempCloud);
	
	std::vector<Point3d>  point;
	std::vector<Point3d>  normal;
	for (int i = 0; i < tempCloud.points.size(); i++) {
		Point3d temp;
		temp.x = tempCloud.points[i].x; temp.y = tempCloud.points[i].y; temp.z = tempCloud.points[i].z;
		point.push_back(temp);
		temp.x = tempCloud.points[i].normal_x; temp.y = tempCloud.points[i].normal_y; temp.z = tempCloud.points[i].normal_z;
		normal.push_back(temp);
	}
	std::vector<vector<int>> triangle;
	for (int i = 0; i < triangles.polygons.size(); i++) {
		vector<int> temp;
		for (int j = 0; j < triangles.polygons[i].vertices.size(); j++) {
			temp.push_back(triangles.polygons[i].vertices[j]);
		}triangle.push_back(temp);
	}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值