PCL MC移动立方体重建(RBF)(Surface_MarchingCubesRBF)

PCL专栏目录及须知

Marching cubes(MC移动立方体3D重建)在HOPPE移动立方体重建一文中讲述了具体原理,本文原理解释,只涉及其RBF移动立方体方法的改进部分。

MC移动立方体重建(HOPPE)

1.RBF的改进

(1)设置离面约束点距离d

(2)根据现有点云数据,求解线性方程组,得到函数f(x)的参数

(3)使用MC方法确定三角面,其中Cube顶点数据值由f(x)定义。

具体流程为:

使用径向基函数(Radial Basis Function,RBF)生成函数空间,其中在表面处的函数值为0。

要成为RBF函数φ(x),需要满足条件:对于某一个固定点c,满足

即对于围绕着某固定点c的等距的x,函数值相同。PCL使用的是这一径向基函数。

我们希望找到一个函数f,对于表面上点x,有f(x)=0。使用RBF函数的线性组合来表示函数f:

另外为避免在不相关的地方产生f(x)=0,将沿表面点的曲面法向量生成了一对离面约束点,一个在表面外,一个在表面内,他们距表面的距离为d,从而可以得到另外2组方程f(x)=d和f(x)=-d。其中距离d不能设置的过大,要保证离面约束点到生成他的点的距离是最近的。如下图所示,4个手指处生成的离面约束点不能交叠。

左图:手部模型;右图手指处表面和2组离面约束点形成表面的示意图


最后上述方程可以组合形成一个线性方程组,求解后即可得到f(x)。然后使用MC方法就可以得到三角化的表面。 

2.完整代码

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/marching_cubes_rbf.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>

int main()
{
	/****************RBF移动立方体重建********************/
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);				// 源点云
	pcl::io::loadPCDFile("D:/code/csdn/data/bunny2.pcd", *cloud);

	// 计算法线
	pcl::NormalEstimation<pcl::PointXYZRGB, pcl::Normal> n;
	pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>);
	n.setInputCloud(cloud);
	n.setSearchMethod(tree);
	n.setKSearch(20);                                                                                   // k邻域搜索范围
	pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
	n.compute(*normals);

	pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudNormals(new pcl::PointCloud<pcl::PointXYZRGBNormal>);         // 连接点云及法向量
	pcl::concatenateFields(*cloud, *normals, *cloudNormals);

	// RBF移动立方体重建
	pcl::MarchingCubes<pcl::PointXYZRGBNormal>::Ptr segmentation(new pcl::MarchingCubesRBF<pcl::PointXYZRGBNormal>);
	pcl::search::KdTree<pcl::PointXYZRGBNormal>::Ptr tree2(new pcl::search::KdTree<pcl::PointXYZRGBNormal>);
	tree2->setInputCloud(cloudNormals);
	segmentation->setInputCloud(cloudNormals);
	segmentation->setIsoLevel(0.0f);													// 提取表面的iso级别
	segmentation->setGridResolution(50, 50, 50);										// 行进立方体网格分辨率
	segmentation->setPercentageExtendGrid(0.0f);										// 定义在点云的边框和网格限制之间的网格内应该保留多少自由空间
	pcl::PolygonMesh triangles;                                                         // 存储最终三角化的网格模型
	segmentation->reconstruct(triangles);
																						
	pcl::io::savePLYFile("D:/code/csdn/data/bunny4.ply", triangles);

	/****************展示********************/
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("GridProjection"));
	viewer->addPointCloud(cloud, "cloud");
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer0(new pcl::visualization::PCLVisualizer("GridProjection0"));
	viewer0->setBackgroundColor(255, 255, 255);
	viewer0->addPolygonMesh(triangles, "triangles");
	viewer0->setRepresentationToWireframeForAllActors();          // 网格模型以线框图模式显示

	while (!viewer->wasStopped() || !viewer0->wasStopped())
	{
		viewer->spinOnce(100);
		viewer0->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}

	return (0);
}

3.结果展示

原始点云

重建展示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值