PCL贪婪投影三角化算法

PCL贪婪投影三角化算法

 

 贪婪投影三角化算法是一种对原始点云进行快速三角化的算法,该算法假设曲面光滑,点云密度变化均匀,不能在三角化的同时对曲面进行平滑和孔洞修复。

方法:

(1)将三维点通过法线投影到某一平面

(2)对投影得到的点云作平面内的三角化

(3)根据平面内三位点的拓扑连接关系获得一个三角网格曲面模型

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

该算法适用于采样点云来自表面连续光滑的曲面且点云的密度变化比较均匀的情况

#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/io/obj_io.h>
#include <pcl/surface/gp3.h>
#include <pcl/visualization/pcl_visualizer.h>

int main(int argc, char** argv) {
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
    pcl::PCLPointCloud2 cloud_blob;

    
    //*打开点云文件
    if (pcl::io::loadPCDFile(argv[1], cloud_blob) == -1) {
        PCL_ERROR("Couldn't read file rabbit.pcd
");
        return(-1);
    }
    pcl::fromPCLPointCloud2(cloud_blob, *cloud);

    //法线估计对象
    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);
    n.setInputCloud(cloud);
    n.setSearchMethod(tree);
    n.setKSearch(20);
    //估计法线存储到其中
    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, *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(200.0f);
    //设置各种参数值
    gp3.setMu(2.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);

    //保存网格图  
    //pcl::io::saveOBJFile("result.obj", triangles);
    std::string output_dir = "cloud_mesh.ply";
    std::string sav = "saved mesh in:";
    sav += output_dir;
    pcl::console::print_info(sav.c_str());
    std::cout << std::endl;

    pcl::io::savePLYFileBinary(output_dir.c_str(), triangles);

    // 显示结果图  
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("MAP3D MESH"));
    ////设置背景;
    viewer->setBackgroundColor(0, 0, 0);
    //设置显示的网格
    viewer->addPolygonMesh(triangles, "my");
    //viewer->initCameraParameters();
    while (!viewer->wasStopped()) {
        viewer->spin();
    }
    std::cout << "success" << std::endl;
    return 0;
}

原文地址:https://www.cnblogs.com/codeAndlearn/p/14230877.html