PCL专栏目录及须知
1.网格投影曲面重建
使用八叉树,通过分辨率和深度的设置,对点云进行体素化的分割,并通过对空洞体素点附近的点进行加权平均,填充相应体素块,填补空洞,得到结果文件。
如下图:
我们要填补红色这一块空洞区域,那么就计算该区域附近几个体素块的加权平均数,然后填充相应体素块,弥补空洞。
计算较慢,参考意义不大。
2.关键函数
(1)网格分辨率
segmentation.setResolution(0.005);
(2)填充空洞时,创建的填充单元格的数量(从种子点开始,每个维度分别填充n个八叉树体素块)
segmentation.setPaddingSize(3);
3.完整代码
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/grid_projection.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
int main()
{
/****************网格投影曲面重建********************/
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);
// 网格投影曲面重建
pcl::GridProjection<pcl::PointXYZRGBNormal> segmentation;
pcl::search::KdTree<pcl::PointXYZRGBNormal>::Ptr tree2(new pcl::search::KdTree<pcl::PointXYZRGBNormal>);
segmentation.setInputCloud(cloudNormals);
segmentation.setSearchMethod(tree2);
segmentation.setResolution(0.005); // 网格分辨率
segmentation.setPaddingSize(3); // 填充空洞时,创建的填充单元格的数量
pcl::PolygonMesh triangles; // 存储最终三角化的网格模型
segmentation.reconstruct(triangles);
pcl::io::savePLYFile("D:/code/csdn/data/bunny3.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->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);
}
4.结果展示
原始点云
重建结果