PCL --- 点云平滑

1.1 点云表面法线

① 点云的法线计算一般有两种方法:

  • 使用曲面重建方法,从点云数据中得到采样点对应的曲面,然后再用曲面模型计算其表面的法线
  • 直接使用近似值直接从点云数据集推断出曲面法线

#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");  // 在点云上显示法线

1.2 滑动最小二乘法 pcl::MovingLeastSquares 可进行上采样

MovingLeastSquares平滑原理 : 将点云进行了MLS的映射,使得输出的点云更加平滑。此类主要适用于点云的光顺处理,当然输入的点云最好是滤过离群点之后的点集,否则将会牺牲表面拟合精度的代价来获得输出点云。平滑的同时可以进行小区域的上采样
输入数据类型 PointXYZPointCloud2
代码示例

#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
  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值