目录
一、概述
1.1原理
1.2实现步骤
1.3应用场景
二、代码实现
2.1关键函数
2.1.1 可视化原始点云和上采样后的点云
2.1.2 MLS 上采样
2.2完整代码
三、实现效果
PCL点云算法汇总及实战案例汇总的目录地址链接:
PCL点云算法与项目实战案例汇总(长期更新)
一、概述
MLS(Moving Least Squares)上采样 是一种用于平滑化和重建点云表面的技术。通过在点云中计算局部的加权平均,MLS 可以生成光滑的表面,并填补点云中的孔洞。此方法特别适合处理稀疏或有噪声的点云数据。
1.1原理
MLS 上采样的核心原理是通过计算点的邻域来拟合一个局部表面(例如平面或曲面)。每个点会根据其邻域内的其他点进行调整,生成新的点,从而实现上采样。利用法线信息可以提升表面细节的保留。
1.2实现步骤
- 读取点云数据。
- 设置 MLS 算法的参数,包括搜索半径和拟合选项。
- 进行上采样处理。
- 可视化原始点云和上采样后的点云。
1.3应用场景
- 点云平滑:去除点云中的噪声。
- 表面重建:在稀疏点云中填补孔洞。
- 特征保留:保持点云的几何特征。
二、代码实现
2.1关键函数
2.1.1 可视化原始点云和上采样后的点云
通过设置不同的视口和背景颜色,分别显示原始点云和上采样后的点云。
#include <pcl/visualization/pcl_visualizer.h>
// 可视化原始点云和上采样后的点云
void visualizePointClouds(
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, // 原始点云
pcl::PointCloud<pcl::PointNormal>::Ptr upsampled_cloud) // 上采样后的点云
{
// 创建可视化器
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("MLS Upsampling Viewer"));
// 设置视口1,显示原始点云
int vp_1;
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1); // 创建左侧窗口
viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_1); // 设置白色背景
viewer->addText("Original PointCloud", 10, 10, "vp1_text", vp_1); // 添加标题
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color_handler(cloud, 0, 255, 0); // 设置颜色为绿色
viewer->addPointCloud(cloud, cloud_color_handler, "original_cloud", vp_1); // 添加点云
// 设置视口2,显示上采样后的点云
int vp_2;
viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2); // 创建右侧窗口
viewer->setBackgroundColor(0.98, 0.98, 0.98, vp_2); // 设置浅灰色背景
viewer->addText("Upsampled PointCloud", 10, 10, "vp2_text", vp_2); // 添加标题
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointNormal> upsampled_color_handler(upsampled_cloud, 255, 0, 0); // 设置颜色为红色
viewer->addPointCloud(upsampled_cloud, upsampled_color_handler, "upsampled_cloud", vp_2); // 添加上采样点云
// 设置点的大小
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 4, "original_cloud", vp_1);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 4, "upsampled_cloud", vp_2);
// 启动可视化循环
while (!viewer->wasStopped())
{
viewer->spinOnce(100); // 刷新可视化器
}
}
2.1.2 MLS 上采样
在这个部分,我们设置 MLS 的参数并执行上采样处理。
// -----------------------------MLS 上采样---------------------------------
pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointNormal> mls; // 创建 MLS 上采样对象
mls.setInputCloud(cloud); // 设置输入点云
// 设置 Kd 树搜索
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>()); // 创建 Kd 树
mls.setSearchMethod(tree); // 将 Kd 树设置为搜索方法
// 设置 MLS 参数
mls.setSearchRadius(0.1); // 设置邻域搜索半径
mls.setComputeNormals(true); // 启用法线计算,这对 MLS 处理非常重要
mls.setPolynomialFit(true); // 启用多项式拟合,以便在每个局部邻域内进行表面拟合
mls.setUpsamplingMethod(pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointNormal>::SAMPLE_LOCAL_PLANE); // 设置上采样方法为局部平面采样
mls.setUpsamplingRadius(0.04); // 设置上采样半径,控制新点的生成
mls.setUpsamplingStepSize(0.02); // 设置上采样步长,控制点的分布
mls.setPolynomialOrder(2); // 设置多项式拟合的阶数,通常选择2以获得较好的平滑效果
// 执行上采样处理
pcl::PointCloud<pcl::PointNormal>::Ptr upsampled_cloud(new pcl::PointCloud<pcl::PointNormal>); // 存储上采样后的点云
mls.process(*upsampled_cloud); // 进行上采样处理
std::cout << "上采样后点云的个数:" << upsampled_cloud->points.size() << std::endl; // 输出上采样后的点云数量
2.2完整代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/surface/mls.h>
#include <pcl/search/kdtree.h>
#include <pcl/visualization/pcl_visualizer.h>
// 可视化原始点云和上采样后的点云
void visualizePointClouds(
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, // 原始点云
pcl::PointCloud<pcl::PointNormal>::Ptr upsampled_cloud) // 上采样后的点云
{
// 创建可视化器
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("MLS Upsampling Viewer"));
// 设置视口1,显示原始点云
int vp_1;
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1); // 创建左侧窗口
viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_1); // 设置白色背景
viewer->addText("Original PointCloud", 10, 10, "vp1_text", vp_1); // 添加标题
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color_handler(cloud, 0, 255, 0); // 设置颜色为绿色
viewer->addPointCloud(cloud, cloud_color_handler, "original_cloud", vp_1); // 添加点云
// 设置视口2,显示上采样后的点云
int vp_2;
viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2); // 创建右侧窗口
viewer->setBackgroundColor(0.98, 0.98, 0.98, vp_2); // 设置浅灰色背景
viewer->addText("Upsampled PointCloud", 10, 10, "vp2_text", vp_2); // 添加标题
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointNormal> upsampled_color_handler(upsampled_cloud, 255, 0, 0); // 设置颜色为红色
viewer->addPointCloud(upsampled_cloud, upsampled_color_handler, "upsampled_cloud", vp_2); // 添加上采样点云
// 设置点的大小
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 4, "original_cloud", vp_1);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 4, "upsampled_cloud", vp_2);
// 启动可视化循环
while (!viewer->wasStopped())
{
viewer->spinOnce(100); // 刷新可视化器
}
}
int main(int argc, char** argv)
{
// -----------------------------读取点云数据---------------------------------
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>("rectangle_cloud.pcd", *cloud) == -1)
{
PCL_ERROR("Couldn't read the PCD file!\n");
return -1; // 返回错误
}
std::cout << "原始点云的个数:" << cloud->points.size() << std::endl; // 输出原始点云数量
// -----------------------------MLS 上采样---------------------------------
pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointNormal> mls; // 创建 MLS 上采样对象
mls.setInputCloud(cloud); // 设置输入点云
// 设置 Kd 树搜索
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
mls.setSearchMethod(tree); // 将 Kd 树设置为搜索方法
// 设置 MLS 参数
mls.setSearchRadius(0.1); // 设置邻域搜索半径
mls.setComputeNormals(true); // 启用法线计算,这对 MLS 处理非常重要
mls.setPolynomialFit(true); // 启用多项式拟合,以便在每个局部邻域内进行表面拟合
mls.setUpsamplingMethod(pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointNormal>::SAMPLE_LOCAL_PLANE); // 设置上采样方法为局部平面采样
mls.setUpsamplingRadius(0.04); // 设置上采样半径,控制新点的生成
mls.setUpsamplingStepSize(0.02); // 设置上采样步长,控制点的分布
mls.setPolynomialOrder(2); // 设置多项式拟合的阶数,通常选择2以获得较好的平滑效果
pcl::PointCloud<pcl::PointNormal>::Ptr upsampled_cloud(new pcl::PointCloud<pcl::PointNormal>); // 存储上采样后的点云
mls.process(*upsampled_cloud); // 执行上采样处理
std::cout << "上采样后点云的个数:" << upsampled_cloud->points.size() << std::endl; // 输出上采样后点云数量
// -----------------------------可视化原始点云和上采样后的点云---------------------------------
visualizePointClouds(cloud, upsampled_cloud); // 可视化函数
return 0;
}