赞
踩
① 点云的法线计算一般有两种方法:
②
#include <pcl/features/normal_3d.h>
// 法线估计
pcl::NormalEstimation<PointT, pcl::Normal> normalEstimation; //创建法线估计的对象
normalEstimation.setInputCloud(cloud_smoothed); //输入点云
pcl::search::KdTree<PointT>::Ptr tree(new pcl::search::KdTree<PointT>); // 创建用于最近邻搜索的KD-Tree
normalEstimation.setSearchMethod(tree);
pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>); // 定义输出的点云法线
// K近邻确定方法,使用k个最近点,或者确定一个以r为半径的圆内的点集来确定都可以,两者选1即可
normalEstimation.setKSearch(10); // 使用当前点周围最近的10个点
//normalEstimation.setRadiusSearch(0.03); //对于每一个点都用半径为3cm的近邻搜索方式
normalEstimation.compute(*normals); //计算法线
//viewer->addPointCloudNormals<PointT, pcl::Normal> (cloud_smoothed, normals, 20, 0.05, "normals"); // 在点云上显示法线
pcl::MovingLeastSquares
可进行上采样MovingLeastSquares平滑原理 : 将点云进行了MLS的映射,使得输出的点云更加平滑。此类主要适用于点云的光顺处理,当然输入的点云最好是滤过离群点之后的点集,否则将会牺牲表面拟合精度的代价来获得输出点云。平滑的同时可以进行小区域的上采样
输入数据类型 :PointXYZ
、PointCloud2
代码示例 :
#include <pcl/surface/mls.h>
pcl::PointCloud<pcl::PointNormal>::Ptr smoothedCloud(new pcl::PointCloud<pcl::PointNormal>);
// Smoothing object (we choose what point types we want as input and output).
pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointNormal> filter;
pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree;
filter.setInputCloud(cloud);
filter.setUpsamplingMethod(); // 增加密度较小区域的密度对于holes的填补却无能为力,具体方法要结合参数使用
filter.setSearchRadius(10);// 用于拟合的K近邻半径。在这个半径里进行表面映射和曲面拟合。半径越小拟合后曲面的失真度越小,反之有可能出现过拟合的现象。
filter.setPolynomialFit(true); // 对于法线的估计是有多项式还是仅仅依靠切线。true为加多项式;false不加,速度较快
filter.setPolynomialFit(3); // 拟合曲线的阶数
filter.setComputeNormals(true); // 是否存储点云的法向量,true 为存储,false 不存储
filter.setSearchMethod(kdtree);
filter.process(*smoothedCloud); // 输出
pcl::copyPointCloud(*smoothedCloud, *cloudOut);
inline void setUpsamplingMethod(UpsamplingMethodmethod) 这个函数比较特殊,他会调用不同的枚举变量, 每个枚举变量有对应的几个不同的函数,因此这里我将一一解释。
经过试验证明:这个upsampling函数只能增加密度较小区域的密度对于holes的填补却无能为力(本来想着用之填补点云缺失的部分,却发现此函数并没有那么强大)。接下来将会一一介绍四个不同的方法。
a) NONE 将不会进行upsampling
b) SAMPLE_LOCAL_PLANE 这个方法就是参考论文中采用的方法,当然此方法所需的计算强度也相当庞大。若使用此方法,将需要调用两个函数:
A. Inline voidsetUpsamplingRadius(double radius) 此函数规定了点云增长的区域。可以这样理解:把整个点云按照此半径划分成若干个子点云,然后一一索引进行点云增长。
B. Inline voidsetUpsamlingStepSize(double size) 对于每个子点云处理时迭代的步长。
c) RANDOM_UNIFORM_DENSITY 也是使用上面子点云的原理,只不过它使得稀疏区域的密度增加,从而使得整个点云的密度均匀。它需要调用函数:inline void setPointDensity(int desired_num_po-ints_in_radius) 注意此函数输入整型变量,意为半径内点的个数。(这个半径应该是search的半径,不需要重新设置)。
d) VOXEL_GRID_DILATION 这个方法有两个步骤:首先将点云以voxels分割,然后进行迭代使得voxels的数目增加。它的结果是:填充空洞和平均化点云的密度。它需要调用的函数为:
A. Inline voidsetDilationVoxelSize(float voxel_size) 设定voxel的大小。
B. Inline voidsetDilationIterations(int iterations) 设置迭代的次数。
————————————————
版权声明:本文为CSDN博主「步子小不扯淡」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012337034/article/details/37534869
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。