pcl几种表面重建

10 篇文章 11 订阅
#include "pch.h"
using namespace std;
#include <pcl/point_types.h>          //PCL中所有点类型定义的头文件
#include <pcl/io/pcd_io.h>            //打开关闭pcd文件的类定义的头文件
#include <pcl/io/ply_io.h>
#include <pcl/io/vtk_io.h>//视觉化工具函式库(VTK,Visualization Toolkit) 模型
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/filters/passthrough.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/kdtree/kdtree_flann.h>  //kd-tree搜索对象的类定义的头文件
#include <pcl/segmentation/extract_clusters.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/io/pcd_io.h> //PCL的PCD格式文件的输入输出头文件
#include <pcl/point_types.h> //PCL对各种格式的点的支持头文件
#include <pcl/search/kdtree.h>//kdtree搜索对象的类定义的头文件
#include <pcl/features/normal_3d.h>//法向量特征估计相关类定义的头文件
//重构
#include <pcl/surface/gp3.h>
#include <pcl/surface/poisson.h>
#include <pcl/surface/mls.h>          //最小二乘法平滑处理类定义头文件
#include <pcl/surface/marching_cubes_hoppe.h>// 移动立方体算法
#include <pcl/surface/marching_cubes_rbf.h>

typedef pcl::PointXYZ PoinT;
typedef pcl::PointNormal PoinTNormal;

int main(int argc, char** argv)
{
    string name = "model";
    pcl::PointCloud<PoinT>::Ptr cloud(new pcl::PointCloud<PoinT>());
    // 加载pcd文件
    pcl::io::loadPCDFile(name + "-ece1.pcd", *cloud);
    std::cerr << "Cloud before filtering: " << std::endl;
    std::cerr << *cloud << std::endl;

    // for(int nIndex = 0; nIndex < cloud->points.size(); nIndex++)
    // {
    //     cloud->points[nIndex].x *= 100;
    //     cloud->points[nIndex].y *= 100;
    //     cloud->points[nIndex].z *= 100;
    // }

    // 计算法向量
    pcl::NormalEstimation<PoinT, pcl::Normal> n;//法线估计对象
    pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);//存储估计的法线
    pcl::search::KdTree<PoinT>::Ptr tree(new pcl::search::KdTree<PoinT>);//定义kd树指针
    tree->setInputCloud(cloud);                        //用cloud构建tree对象
    n.setInputCloud(cloud);                            //为法线估计对象设置输入点云
    n.setSearchMethod(tree);                          //设置搜索方法
    n.setKSearch(20);                                 //设置k搜索的k值为20
    n.compute(*normals);                              //估计法线存储结果到normals中
    //将点云和法线放到一起
    pcl::PointCloud<PoinTNormal>::Ptr cloud_with_normals(new pcl::PointCloud<PoinTNormal>);
    pcl::concatenateFields(*cloud, *normals, *cloud_with_normals);//连接字段,cloud_with_normals存储有向点云
    std::cerr << "法线计算   完成" << std::endl;

    //创建搜索树
    pcl::search::KdTree<PoinTNormal>::Ptr tree2(new pcl::search::KdTree<PoinTNormal>);
    tree2->setInputCloud(cloud_with_normals);

    // 曲面重建
    pcl::MovingLeastSquares<PoinTNormal, PoinTNormal> mls;
    mls.setComputeNormals(true);  //设置在最小二乘计算中需要进行法线估计
    mls.setInputCloud(cloud_with_normals);//设置参数
    mls.setPolynomialFit(true);
    mls.setSearchMethod(tree2);
    mls.setSearchRadius(0.03);
    pcl::PointCloud<PoinTNormal>::Ptr cloud_with_normals_msl(new pcl::PointCloud<PoinTNormal>);
    mls.process(*cloud_with_normals_msl);
    cloud_with_normals = cloud_with_normals_msl;
    std::cerr << "曲面重建   完成" << std::endl;

    // 开始表面重建 ********************************************************************

    //创建Poisson对象,并设置参数
    pcl::Poisson<pcl::PointNormal> pn;
    pn.setConfidence(false); //是否使用法向量的大小作为置信信息。如果false,所有法向量均归一化。
    pn.setDegree(2); //设置参数degree[1,5],值越大越精细,耗时越久。
    pn.setDepth(8);
    //树的最大深度,求解2^d x 2^d x 2^d立方体元。
    // 由于八叉树自适应采样密度,指定值仅为最大深度。
    pn.setIsoDivide(8); //用于提取ISO等值面的算法的深度
    pn.setManifold(false); //是否添加多边形的重心,当多边形三角化时。 
    // 设置流行标志,如果设置为true,则对多边形进行细分三角话时添加重心,设置false则不添加
    pn.setOutputPolygons(false); //是否输出多边形网格(而不是三角化移动立方体的结果)
    pn.setSamplesPerNode(3.0); //设置落入一个八叉树结点中的样本点的最小数量。无噪声,[1.0-5.0],有噪声[15.-20.]平滑
    pn.setScale(1.25); //设置用于重构的立方体直径和样本边界立方体直径的比率。
    pn.setSolverDivide(8); //设置求解线性方程组的Gauss-Seidel迭代方法的深度
    //pn.setIndices();
    //设置搜索方法和输入点云
    pn.setSearchMethod(tree2);
    pn.setInputCloud(cloud_with_normals);
    //创建多变形网格,用于存储结果
    pcl::PolygonMesh mesh;
    //执行重构
    pn.performReconstruction(mesh);
    //保存网格图
    pcl::io::savePLYFile(name + "-poisson.ply", mesh);
    std::cerr << "泊松重建   完成" << std::endl;


    // // 贪婪投影三角化算法
    // pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;   // 定义三角化对象
    // pcl::PolygonMesh mesh;                // 存储最终三角化的网络模型
    // // Set the maximum distance between connected points (maximum edge length)
    // gp3.setSearchRadius(0.025);  // 设置连接点之间的最大距离,(即是三角形最大边长)
    // // 设置各参数值
    // gp3.setMu(2.5);  // 设置被样本点搜索其近邻点的最远距离为2.5,为了使用点云密度的变化
    // gp3.setMaximumNearestNeighbors(100);// 设置样本点可搜索的邻域个数
    // gp3.setMaximumSurfaceAngle(M_PI / 4);  // 设置某点法线方向偏离样本点法线的最大角度45
    // gp3.setMinimumAngle(M_PI / 18);        // 设置三角化后得到的三角形内角的最小的角度为10
    // gp3.setMaximumAngle(2 * M_PI / 3);       // 设置三角化后得到的三角形内角的最大角度为120
    // gp3.setNormalConsistency(false);     // 设置该参数保证法线朝向一致
    // // Get result
    // gp3.setInputCloud(cloud_with_normals);// 设置输入点云为有向点云
    // gp3.setSearchMethod(tree2);               // 设置搜索方式
    // gp3.reconstruct(mesh);               // 重建提取三角化
    // // 附加顶点信息
    // std::vector<int> parts = gp3.getPartIDs();
    // std::vector<int> states = gp3.getPointStates();
    // // 保存mesh文件
    // pcl::io::saveVTKFile(name + "-quick.ply", mesh);
    // std::cerr << "快速三角化 完成" << std::endl;


    // //移动立方体算法
    // pcl::MarchingCubes<pcl::PointNormal> *mc;
    // mc = new pcl::MarchingCubesHoppe<pcl::PointNormal>();
    // /*
    //   if (hoppe_or_rbf == 0)
    //     mc = new pcl::MarchingCubesHoppe<pcl::PointNormal> ();
    //   else
    //   {
    //     mc = new pcl::MarchingCubesRBF<pcl::PointNormal> ();
    //     (reinterpret_cast<pcl::MarchingCubesRBF<pcl::PointNormal>*> (mc))->setOffSurfaceDisplacement (off_surface_displacement);
    //   }
    // */
    // //创建多变形网格,用于存储结果
    // pcl::PolygonMesh mesh;
    // //设置MarchingCubes对象的参数
    // mc->setIsoLevel(0.0f);
    // mc->setGridResolution(50, 50, 50);
    // mc->setPercentageExtendGrid(0.0f);
    // //设置搜索方法
    // mc->setInputCloud(cloud_with_normals);
    // //执行重构,结果保存在mesh中
    // mc->reconstruct(mesh);
    // //保存网格图
    // pcl::io::saveVTKFile(name + "-cubes.ply", mesh);
    // std::cerr << "移动立方体 完成" << std::endl;



    // 显示结果图
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D viewer"));
    viewer->setBackgroundColor(0, 0, 0);
    viewer->addPolygonMesh(mesh, "my");
    viewer->addCoordinateSystem(50.0);
    viewer->initCameraParameters();
    while (!viewer->wasStopped()) {
        viewer->spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }

    return 0;

}

效果一览

原始点云

在这里插入图片描述

泊松重建算法

不使用最小二乘平滑

在这里插入图片描述

使用最小二乘平滑

在这里插入图片描述

快速三角化算法

(使用最小二乘平滑)
在这里插入图片描述

移动立方体算法

(使用最小二乘平滑)
在这里插入图片描述

  • 16
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
三维泊松表面重建是一种常用的点云数据处理方,可以将离散的点云数据重建成连续的三维表面模型。PCL(Point Cloud Library)是一个开源的点云处理库,提供了许多实用的算和工具函数,包括三维泊松表面重建。 在PCL中使用三维泊松表面重建,你可以按照以下步骤进行操作: 1. 使用PCL加载点云数据:首先,你需要使用PCL库中的函数将点云数据加载到程序中。可以使用`pcl::io::loadPCDFile()`函数加载`.pcd`格式的点云文件,或者使用其他合适的函数加载其他格式的点云数据。 2. 对点云进行预处理:在进行泊松表面重建之前,有时需要对点云进行预处理,例如去除离群点、滤波等。PCL提供了许多预处理的方,可以根据具体情况选择合适的方进行处理。 3. 执行三维泊松表面重建使用`pcl::Poisson`类可以进行三维泊松表面重建。你需要创建一个`pcl::Poisson`对象,并将预处理后的点云数据传递给它。然后,调用`performReconstruction()`函数执行重建过程。 4. 获取重建的三维模型:重建完成后,你可以使用`pcl::PolygonMesh`对象来获取重建的三维模型。可以使用`pcl::toPCLPointCloud2()`函数将重建的模型转换为点云格式,或者直接保存为`.ply`等格式的文件。 需要注意的是,三维泊松表面重建是一个计算密集型的算,对于大规模的点云数据可能需要较长的运行时间。此外,泊松表面重建的结果可能受到输入点云的质量和密度等因素的影响,需要根据具体情况进行调整和优化。 希望以上信息对你有帮助!如果你还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值