PCL点云曲面重建（1）

0
0
0
1. 云栖社区>
2. 博客>
3. 正文

## PCL点云曲面重建（1）

being_young123 2017-03-08 20:19:00 浏览762

（1）用最小二乘法对点云进行平滑处理

```#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>  //kd-tree搜索对象的类定义的头文件
#include <pcl/surface/mls.h>        //最小二乘法平滑处理类定义头文件

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

// 创建 KD-Tree
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);

// Output has the PointNormal type in order to store the normals calculated by MLS
pcl::PointCloud<pcl::PointNormal> mls_points;

// 定义最小二乘实现的对象mls
pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointNormal> mls;

mls.setComputeNormals (true);  //设置在最小二乘计算中需要进行法线估计

// Set parameters
mls.setInputCloud (cloud);
mls.setPolynomialFit (true);
mls.setSearchMethod (tree);

// Reconstruct
mls.process (mls_points);

// Save output
pcl::io::savePCDFile ("bun0-mls.pcd", mls_points);
}```

(2)在平面模型上提取凸（凹）多边形

```#include <pcl/ModelCoefficients.h>           //采样一致性模型相关类头文件
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/project_inliers.h>          //滤波相关类头文件
#include <pcl/segmentation/sac_segmentation.h>   //基于采样一致性分割类定义的头文件
#include <pcl/surface/concave_hull.h>                 //创建凹多边形类定义头文件

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

// 建立过滤器消除杂散的NaN
pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud (cloud);                  //设置输入点云
pass.setFilterFieldName ("z");             //设置分割字段为z坐标
pass.setFilterLimits (0, 1.1);             //设置分割阀值为(0, 1.1)
pass.filter (*cloud_filtered);
std::cerr << "PointCloud after filtering has: "
<< cloud_filtered->points.size () << " data points." << std::endl;

pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
pcl::PointIndices::Ptr inliers (new pcl::PointIndices);   //inliers存储分割后的点云
// 创建分割对象
pcl::SACSegmentation<pcl::PointXYZ> seg;
// 设置优化系数，该参数为可选参数
seg.setOptimizeCoefficients (true);
// Mandatory
seg.setModelType (pcl::SACMODEL_PLANE);
seg.setMethodType (pcl::SAC_RANSAC);
seg.setDistanceThreshold (0.01);

seg.setInputCloud (cloud_filtered);
seg.segment (*inliers, *coefficients);
std::cerr << "PointCloud after segmentation has: "
<< inliers->indices.size () << " inliers." << std::endl;

// Project the model inliers
pcl::ProjectInliers<pcl::PointXYZ> proj;//点云投影滤波模型
proj.setModelType (pcl::SACMODEL_PLANE); //设置投影模型
proj.setIndices (inliers);
proj.setInputCloud (cloud_filtered);
proj.setModelCoefficients (coefficients);      //将估计得到的平面coefficients参数设置为投影平面模型系数
proj.filter (*cloud_projected);            //得到投影后的点云
std::cerr << "PointCloud after projection has: "
<< cloud_projected->points.size () << " data points." << std::endl;

// 存储提取多边形上的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZ>);
pcl::ConcaveHull<pcl::PointXYZ> chull;        //创建多边形提取对象
chull.setInputCloud (cloud_projected);       //设置输入点云为提取后点云
chull.setAlpha (0.1);
chull.reconstruct (*cloud_hull);   //创建提取创建凹多边形

std::cerr << "Concave hull has: " << cloud_hull->points.size ()
<< " data points." << std::endl;

pcl::PCDWriter writer;
writer.write ("table_scene_mug_stereo_textured_hull.pcd", *cloud_hull, false);

return (0);
}```

（3）无序点云的快速三角化

（1）先将有向点云投影到某一局部二维坐标平面内

（2）在坐标平面内进行平面内的三角化

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

```#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h>      //贪婪投影三角化算法

int
main (int argc, char** argv)
{
// 将一个XYZ点类型的PCD文件打开并存储到对象中
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::PCLPointCloud2 cloud_blob;
pcl::fromPCLPointCloud2 (cloud_blob, *cloud);
//* the data should be available in cloud

// Normal estimation*
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;      //法线估计对象
pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);   //存储估计的法线
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);  //定义kd树指针
tree->setInputCloud (cloud);   ///用cloud构建tree对象
n.setInputCloud (cloud);
n.setSearchMethod (tree);
n.setKSearch (20);
n.compute (*normals);       ////估计法线存储到其中
//* normals should not contain the point normals + surface curvatures

// Concatenate the XYZ and normal fields*
pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals (new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields (*cloud, *normals, *cloud_with_normals);    //连接字段
//* cloud_with_normals = cloud + normals

//定义搜索树对象
pcl::search::KdTree<pcl::PointNormal>::Ptr tree2 (new pcl::search::KdTree<pcl::PointNormal>);
tree2->setInputCloud (cloud_with_normals);   //点云构建搜索树

// Initialize objects
pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;   //定义三角化对象
pcl::PolygonMesh triangles;                //存储最终三角化的网络模型

// Set the maximum distance between connected points (maximum edge length)

// 设置各参数值
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 (triangles);  //重建提取三角化

// 附加顶点信息
std::vector<int> parts = gp3.getPartIDs();
std::vector<int> states = gp3.getPointStates();

// Finish
return (0);
}```

首先看一下原来的PCD可视化文件

being_young123
+ 关注