背景
在测量较小的对象时会产生一些误差,这误差所造成的不规则数据如果直接拿来进行曲面重建的话会使得重建的曲面不光滑或而有漏洞。
MLS算法原理
基于最小二乘法(Least Squares)将点云数据进行多项拟合,并使用拟合的结果对点云进行平滑处理。
MLS算法与高斯滤波在平滑点云方面的差别
高斯滤波基于高斯函数,它会给每个点的领域点分配一个权重。然后通过将邻域点的坐标进行加权平均来实现平滑。这种方法简单快速,并且可以减少点云中的噪声,但它对点云中的不规则处理不够好,边缘细节可能会模糊。
MLS算法则更加复杂一些。它通过对点云数据进行多项式拟合,找到一个适合该点云局部取于的函数曲线。然后通过这个曲线来重新计算每个点的坐标,从而实现点云的平滑处理。这种方法可以更好地处理点云中的不规则形和非均匀性,提供更准确的平滑结果。
总之,高斯滤波是一种简单而快速的方法,适合噪声较少的点云,金额一帮助平滑点云表面。而MLS算法更复杂,适用于更复杂的点云平滑任务,可以更好地处理不规则性和非均匀性,并提供准确的平滑结果。
代码:
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/search/search.h>
#include <pcl/search/kdtree.h>
#include <pcl/surface/mls.h>
#include <pcl/visualization/cloud_viewer.h>
// -----------------------------------------------------------
// 使用PCL库中的MovngLeastSquares算法对输入的点云数据进行平滑和法线估计
// ------------------------------------------------------------
int main(){
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile("/home/jason/file/pcl-data/data/tutorials/ism_train_cat.pcd",
*cloud) < 0){
std::cout << "cloud point read err!" << std::endl;
return -1;
}
// pcl::search::Kdtree,<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
pcl::search::Search<pcl::PointXYZ>::Ptr tree = std::shared_ptr<pcl::search::Search<pcl::PointXYZ>>(new pcl::search::KdTree<pcl::PointXYZ>); // 新建KdTree搜索对象,用于后续最近邻搜索
pcl::PointCloud<pcl::PointNormal> mls_points; // 用于存储经过MovingLeastSquares算法处理后点云及法线信息
pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointNormal> mls; // 创建MovingLeastSquares对象,用于执行平滑和法线估计操作
mls.setComputeNormals(true); // 设置进行法线估计
mls.setInputCloud(cloud); // 输入点云
mls.setPolynomialOrder(2); // 多项式的阶数为2
mls.setSearchMethod(tree);// 设置最近邻搜索方法为之前创建的KdTree对象
mls.setSearchRadius(0.03); // 设置i半径为0.03
mls.process(mls_points); // 执行MovingLeatSqures算法
// 保存处理后的点云数据和法线信息
if(mls_points.size() > 0){
pcl::io::savePCDFileASCII("/home/jason/file/pcl-learning/11surface表面/1基于多项式重构的平滑和法线估计/result.pcd", mls_points);
}else {
std::cout << "算法结果:" << mls_points.size() << std::endl;
std::cout << "保存数据为空." << std::endl;
}
pcl::visualization::CloudViewer viewer("cloud Viewer");
viewer.showCloud(cloud);
while (!viewer.wasStopped()) {
}
}
参考:
PCL学习笔记(三十二)-- 基于多项式平滑点云及法线估计的曲面重建_pcl::pointnormal的生成_看到我请叫我学C++的博客-CSDN博客