#include <pcl/point_types.h>
#include <pcl/io/ply_io.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/surface/mls.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h>
#include <pcl/visualization/pcl_visualizer.h>
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloudT;
typedef pcl::PointNormal NormalT;
typedef pcl::PointCloud<NormalT> PointCloudWithNormals;
int main(int argc, char** argv) {
// 1. 读取点云数据
PointCloudT::Ptr cloud(new PointCloudT);
if (pcl::io::loadPLYFile<PointT>("D:\\Model\\pointcloud.ply", *cloud) == -1) {
std::cerr << "Error loading point cloud" << std::endl;
return -1;
}
// 2. 预处理 - 去噪
pcl::StatisticalOutlierRemoval<PointT> sor;
sor.setInputCloud(cloud);
sor.setMeanK(50); // 考虑邻近50个点
sor.setStddevMulThresh(1.0); // 标准差倍数阈值
sor.filter(*cloud);
// 3. 下采样
pcl::VoxelGrid<PointT> voxel;
voxel.setInputCloud(cloud);
voxel.setLeafSize(0.5f, 0.5f, 0.5f); // 根据点云密度调整
voxel.filter(*cloud);
// 4. 平滑处理 (移动最小二乘法)
pcl::MovingLeastSquares<PointT, NormalT> mls;
pcl::search::KdTree<PointT>::Ptr tree(new pcl::search::KdTree<PointT>);
mls.setInputCloud(cloud);
mls.setSearchMethod(tree);
mls.setSearchRadius(2.0); // 根据点间距调整
mls.setComputeNormals(true);
PointCloudWithNormals::Ptr cloud_smoothed(new PointCloudWithNormals);
mls.process(*cloud_smoothed);
// 5. 法线估计(如果MLS未计算)
pcl::NormalEstimation<PointT, NormalT> ne;
ne.setInputCloud(cloud);
ne.setSearchMethod(tree);
ne.setRadiusSearch(2.0); // 与MLS半径一致
ne.compute(*cloud_smoothed);
// 6. 贪心投影三角化(适合开放边缘)
pcl::GreedyProjectionTriangulation<NormalT> gp3;
pcl::PolygonMesh triangles;
// 设置重建参数
gp3.setSearchRadius(3.0); // 搜索半径(点间距的3-5倍)
gp3.setMu(2.5); // 最大允许距离乘数
gp3.setMaximumNearestNeighbors(100); // 最大邻近点数
gp3.setMaximumSurfaceAngle(M_PI / 2); // 45度
gp3.setMinimumAngle(M_PI / 18); // 10度
gp3.setMaximumAngle(2 * M_PI / 3); // 120度
gp3.setNormalConsistency(true); // 保持法线一致性
gp3.setInputCloud(cloud_smoothed);
gp3.reconstruct(triangles);
7. 后处理 - 网格平滑
//pcl::MeshSmoothingLaplacianVTK smoother;
//smoother.setInputMesh(triangles);
//smoother.setNumIterations(50); // 平滑迭代次数
//smoother.process(triangles);
// 8. 保存结果
pcl::io::savePLYFile("output_mesh.ply", triangles);
// 可视化 (可选)
pcl::visualization::PCLVisualizer viewer("Mesh Viewer");
viewer.addPolygonMesh(triangles, "mesh");
while (!viewer.wasStopped()) {
viewer.spinOnce();
}
return 0;
}
