Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

CloudCompare二次开发之如何通过PCL进行点云曲面重建?

本文介绍了如何在CloudCompare中通过PCL库进行点云数据处理,特别是利用贪婪三角化方法进行曲面重建的步骤。首先,文章展示了在CloudCompare界面设计重建按钮并连接信号槽函数。接着,详细阐述了点云的下采样、统计异常点去除、重采样、法线估计以及最终的贪婪三角化过程。最后,文章提供了重建前后的对比效果,并引用了多个参考资料作为学习资源。
摘要由CSDN通过智能技术生成

0.引言

  因笔者课题涉及点云处理,需要通过PCL进行点云数据一系列处理分析,查阅现有网络资料,对常用PCL点云曲面重建进行代码实现,本文记录曲面重建实现过程。

1.CloudCompare界面设计重建(reconstruct)按钮

  (1)设计.ui文件
  ①设计按钮
  在这里插入图片描述

  ②编译.ui
  在这里插入图片描述

  (2)修改mainwindow.h文件
  在这里插入图片描述

//点云重建
void doActionPCLSurface_Rec(); // 使用贪婪三角化进行曲面重建

  (3)修改mainwindow.cpp文件
  ①添加头文件
  在这里插入图片描述

#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/voxel_grid.h>  
#include <pcl/filters/statistical_outlier_removal.h>  
#include <pcl/surface/mls.h>  
#include <pcl/features/normal_3d.h>  
#include <pcl/surface/gp3.h>

  ②添加实现代码
  在这里插入图片描述

//使用贪婪三角化进行曲面重建
void MainWindow::doActionPCLSurface_Rec()  
{  
}

  ③添加信号槽函数
  在这里插入图片描述

onnect(m_UI->actionSurface_Rec, &amp;QAction::triggered, this, &amp;MainWindow::doActionPCLSurface_Rec);//使用贪婪三角化进行曲面重建

  (4)生成
  在这里插入图片描述

2.使用贪婪三角化进行曲面重建(Surface_Rec)

  (1)实现代码

typedef pcl::PointXYZ PointT;
//使用贪婪三角化进行曲面重建  
void MainWindow::doActionPCLSurface_Rec() {  
    if (getSelectedEntities().size() != 1)  
    {  
        ccLog::Print(QStringLiteral("只能选择一个点云实体"));  
    return;  
    }  
    ccHObject* entity = getSelectedEntities()[0];  
    ccPointCloud* ccCloud = ccHObjectCaster::ToPointCloud(entity);  
    // ---------------------------读取数据到PCL----------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);  
    cloud->resize(ccCloud->size());  
    for (int i = 0; i < cloud->size(); ++i)  
    {  
        const CCVector3* point = ccCloud->getPoint(i);  
        cloud->points[i].x = point->x;  
        cloud->points[i].y = point->y;  
        cloud->points[i].z = point->z;  
    }  
    pcl::PointCloud<PointT>::Ptr cloud_downSampled(new pcl::PointCloud<PointT>);  
    pcl::PointCloud<PointT>::Ptr cloud_filtered(new pcl::PointCloud<PointT>);  
    pcl::PointCloud<PointT>::Ptr cloud_smoothed(new pcl::PointCloud<PointT>);  
    // 下采样,同时保持点云形状特征  
    pcl::VoxelGrid<PointT> downSampled;  //创建滤波对象  
    downSampled.setInputCloud(cloud);            //设置需要过滤的点云给滤波对象  
    downSampled.setLeafSize(0.01f, 0.01f, 0.01f);  //设置滤波时创建的体素体积为1cm的立方体  
    downSampled.filter(*cloud_downSampled);           //执行滤波处理,存储输出  
    // 统计滤波  
    pcl::StatisticalOutlierRemoval<PointT> statisOutlierRemoval;       //创建滤波器对象  
    statisOutlierRemoval.setInputCloud(cloud_downSampled);            //设置待滤波的点云  
    statisOutlierRemoval.setMeanK(50);                                //设置在进行统计时考虑查询点临近点数  
    statisOutlierRemoval.setStddevMulThresh(3.0);                     //设置判断是否为离群点的阀值:均值+1.0*标准差  
    statisOutlierRemoval.filter(*cloud_filtered);                     //滤波结果存储到cloud_filtered  
     // 对点云重采样  
    pcl::search::KdTree<PointT>::Ptr treeSampling(new pcl::search::KdTree<PointT>);  
    pcl::PointCloud<PointT> mls_point;  
    pcl::MovingLeastSquares<PointT, PointT> mls;  
    mls.setComputeNormals(false);  
    mls.setInputCloud(cloud_filtered);  
    mls.setPolynomialOrder(2);  
    mls.setPolynomialFit(false);  
    mls.setSearchMethod(treeSampling);  
    mls.setSearchRadius(0.05);  
    mls.process(mls_point);  
    // 输出重采样结果  
    cloud_smoothed = mls_point.makeShared();  
    // 法线估计  
    pcl::NormalEstimation<PointT, pcl::Normal> normalEstimation;  
    normalEstimation.setInputCloud(cloud_smoothed);  
    pcl::search::KdTree<PointT>::Ptr tree(new pcl::search::KdTree<PointT>);  
    normalEstimation.setSearchMethod(tree);  
    pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);  
    normalEstimation.setKSearch(10);  
    normalEstimation.compute(*normals);  
    //Triangle Projection  
    pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);  
    pcl::concatenateFields(*cloud_smoothed, *normals, *cloud_with_normals);  
    pcl::search::KdTree<pcl::PointNormal>::Ptr tree2(new pcl::search::KdTree<pcl::PointNormal>);  
    tree2->setInputCloud(cloud_with_normals);  
    pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;  
    pcl::PolygonMesh triangles;  
    gp3.setSearchRadius(0.1);  
    gp3.setMu(2.5);  
    gp3.setMaximumNearestNeighbors(52);  
    gp3.setMaximumAngle(2 * M_PI / 3);  
    gp3.setMinimumAngle(M_PI / 18);  
    gp3.setMaximumSurfaceAngle(M_PI / 4);  
    gp3.setNormalConsistency(false);  
    gp3.setInputCloud(cloud_with_normals);  
    gp3.setSearchMethod(tree2);  
    gp3.reconstruct(triangles);  
    ccPointCloud* newPointCloud = new ccPointCloud(QString("reconstruct_points"));  
    for (int i = 0; i < cloud_with_normals->size(); ++i)  
    {  
        double x = cloud_with_normals->points[i].x;  
        double y = cloud_with_normals->points[i].y;  
        double z = cloud_with_normals->points[i].z;  
        newPointCloud->addPoint(CCVector3(x, y, z));  
    }  
    //创建一个Mesh网格  
    ccMesh* mesh = new ccMesh(newPointCloud);  
    mesh->setName(ccCloud->getName() + "-mesh");  
    unsigned int v1, v2, v3;                //用于接收顶点  
    for (int i = 0; i < triangles.polygons.size(); i++) {  
        v1 = triangles.polygons[i].vertices[0];  
        v2 = triangles.polygons[i].vertices[1];  
        v3 = triangles.polygons[i].vertices[2];  
        mesh->addTriangle(v1, v2, v3);                //通过这种方式来添加三角面片  
    }  
    mesh->setTempColor(ccColor::Rgba(rand() % 255, rand() % 255, rand() % 255, 60));  
    mesh->showColors(true);  
    // ------------------------PCL->CloudCompare--------------------------------  
    if (ccCloud->getParent())  
    {  
        ccCloud->getParent()->addChild(mesh);  
    }  
    ccCloud->setEnabled(false);  
    addToDB(mesh);  
    refreshAll();  
    updateUI();  
}

  (2)重建结果
  ①重建前
  在这里插入图片描述

  ②重建后
  在这里插入图片描述

参考资料:
[1] 来吧!我在未来等你!. CloudCompare二次开发之如何配置PCL点云库?; 2023-05-15 [accessed 2023-05-17].
[2] Tech沉思录. PCL点云使用贪婪三角化进行曲面重构; 2019-09-06 [accessed 2023-05-17].
[3] 大鱼BIGFISH. CloudCompare&PCL AlphaShape算法曲面重建; 2022-10-26 [accessed 2023-05-17].
[4] 点云侠. PCL 泊松曲面重建法(多线程加速版); 2023-02-01 [accessed 2023-05-17].
[5] 悠缘之空. PCL函数库摘要——点云曲面重建; 2021-11-07 [accessed 2023-05-17].

dll函数接口: ////******** 初始化默认参数 ********// //extern "C" int __stdcall ZSY3DViewerInit(); //******** 读取历史数据到cloud ********// extern "C" int __stdcall ZSY3DReadHistoryData(char *file_dir); //******** 读取txt数据到cloud ********// extern "C" int __stdcall ZSY3DReadTxtData(char *file_dir); //******** 读取单个点数据到cloud ********// extern "C" int __stdcall ZSY3DReadSingleData(float x, float y, float z); //******** 读取所有点数据到cloud ********// extern "C" int __stdcall ZSY3DReadNowData(float *x, float *y, float *z, int count); //******** vtk读取txt文件并显示 ********// extern "C" int __stdcall ZSY3DReadFile_TXT(char *file_dir); //******** vtk读取obj文件并显示 ********// extern "C" int __stdcall ZSY3DReadFile_OBJ(char *file_dir); //******** vtk读取vtk文件并显示 ********// extern "C" int __stdcall ZSY3DReadFile_VTK(char *file_dir); //******** vtk读取ply文件并显示 ********// extern "C" int __stdcall ZSY3DReadFile_PLY(char *file_dir); //******** cloud下采样处理 ********// extern "C" int __stdcall ZSY3DDownSampling(float leaf_size); //******** cloud均匀采样处理 ********// extern "C" int __stdcall ZSY3DBalanceSampling(float radiusSearch = 0.01f); //******** cloud增采样处理 ********// extern "C" int __stdcall ZSY3DIncreaseSampling(float radius = 0.03f, float StepSize = 0.02f); //******** cloud直通滤波采样处理 ********// extern "C" int __stdcall ZSY3DStraightSampling(char *fieldName = "z", float limits_min = 0.0f, float limits_max = 0.1f, bool limitsNegative = true); //******** cloud统计滤波采样处理 ********// extern "C" int __stdcall ZSY3DStatisticsSampling(float meanK = 50.0f,float stddevMulThresh = 1.0f); //******** cloud半径滤波采样处理 ********// extern "C" int __stdcall ZSY3DRadiusSampling(float radiusSearch = 0.8f, float minNeighborsInRadius = 2.0f); //******** cloud数据进行渲染,并显示 ********// extern "C" int __stdcall ZSY3DShowPointCloud(); //******** cloud数据进行VTK三维重建(三角面绘制),并显示 ********// extern "C" int __stdcall ZSY3DDelaunayBuild(bool depth_color); //******** cloud数据进行VTK三维重建(曲面体绘制),并显示 ********// extern "C" int __stdcall ZSY3DSurfaceBu
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值