PCL LocalMaximum消除局部最大的点
目录
一、概述
1.1原理
1.2实现步骤
1.3应用场景
二、代码实现
2.1关键函数
2.1.1 设置邻域搜索
2.1.2 可视化函数
2.2完整代码
三、实现效果
PCL点云算法汇总及实战案例汇总的目录地址链接:
PCL点云算法与项目实战案例汇总(长期更新)
一、概述
PCL 中的 LocalMaximum 滤波器是一种用于去除点云数据中局部最大点的过滤器,通常用于点云处理的平滑与降噪。局部最大点是指在某个局部区域中,比周围点具有更大高度或值的点。通过移除这些点,可以消除一些高频噪声和异常点。
1.1原理
LocalMaximum 滤波的基本原理是:对于点云中的每一个点,检查其邻域内的点,如果该点的某个值(如 z 值或强度值)比其邻域中的点更大,则该点被认为是局部最大点,将其移除。
主要步骤如下:
- 邻域搜索:为每个点定义一个邻域(如固定半径或 k 近邻)。
- 比较邻域点:比较邻域中其他点的值(如 z 值或强度),判断是否为局部最大点。
- 移除局部最大点:将这些局部最大点从点云数据中移除。
1.2实现步骤
- 加载点云数据:读取包含点云数据的文件。
- 定义邻域搜索参数:设置邻域搜索的半径或 K 值。
- 应用 LocalMaximum 过滤器:查找并移除局部最大点。
- 可视化结果:展示原始点云和移除局部最大点后的点云。
1.3应用场景
- 去除局部噪声:通过移除局部最大点,能够消除一些高频噪声和异常点。
- 预处理:在平滑或其他处理操作之前,先移除局部极值点来保证数据的稳定性。
- 点云降噪:可用于点云的降噪处理,特别是当噪声表现为局部极大值时。
二、代码实现
2.1关键函数
2.1.1 设置邻域搜索
通过 pcl::search::KdTree 设置邻域搜索,并将其与 LocalMaximum 滤波器结合。
// 局部最大值滤波函数
void applyLocalMaximumFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out, float radius)
{
pcl::LocalMaximum<pcl::PointXYZ> lm;
lm.setInputCloud(cloud_in); // 设置输入点云
lm.setRadius(radius); // 设置搜索半径
lm.filter(*cloud_out); // 执行滤波并保存结果
}
2.1.2 可视化函数
通过 PCLVisualizer 在一个窗口中显示原始点云和移除局部最大点后的点云,包含坐标轴。
#include <pcl/visualization/pcl_visualizer.h>
// 可视化原始点云和过滤后的点云
void visualizePointClouds(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr& filtered_cloud)
{
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Local Maximum Filter Viewer"));
int v1(0), v2(1);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1); // 创建第一个视口
viewer->setBackgroundColor(1.0, 1.0, 1.0, v1); // 白色背景
viewer->addText("Original Point Cloud", 10, 10, "v1 text", v1); // 添加标题
viewer->addPointCloud(cloud, "original_cloud", v1); // 原始点云
viewer->createViewPort(0.5, 0.0, 1.0, 1.0, v2); // 创建第二个视口
viewer->setBackgroundColor(0.98, 0.98, 0.98, v2); // 浅灰色背景
viewer->addText("Filtered Point Cloud", 10, 10, "v2 text", v2); // 添加标题
viewer->addPointCloud(filtered_cloud, "filtered_cloud", v2); // 过滤后的点云
// 设置原始点云为红色,过滤后的点云为绿色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> original_color(cloud, 255, 0, 0);
viewer->updatePointCloud(cloud, original_color, "original_cloud");
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> filtered_color(filtered_cloud, 0, 255, 0);
viewer->updatePointCloud(filtered_cloud, filtered_color, "filtered_cloud");
// 添加坐标系
viewer->addCoordinateSystem(1.0);
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
}
}
2.2完整代码
#include <iostream>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/filters/local_maximum.h> // 局部最大值滤波器
#include <pcl/io/pcd_io.h> // PCD文件读取
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
// 局部最大值滤波函数
void applyLocalMaximumFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out, float radius)
{
pcl::LocalMaximum<pcl::PointXYZ> lm;
lm.setInputCloud(cloud_in); // 设置输入点云
lm.setRadius(radius); // 设置搜索半径
lm.filter(*cloud_out); // 执行滤波并保存结果
}
// 可视化函数
void visualize_cloud(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr& filter_cloud) {
// 创建可视化对象
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("显示点云"));
int v1(0), v2(0);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
viewer->setBackgroundColor(1.0, 1.0, 1.0, v1); // 白色背景
viewer->addText("Original Point Cloud", 10, 10, "v1_text", v1);
viewer->createViewPort(0.5, 0.0, 1, 1.0, v2);
viewer->setBackgroundColor(0.98, 0.98, 0.98, v2); // 灰色背景
viewer->addText("Filtered Point Cloud", 10, 10, "v2_text", v2);
// 原始点云显示为红色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> original_color(cloud, 255, 0, 0);
viewer->addPointCloud(cloud, original_color, "original_cloud", v1);
// 过滤后的点云显示为绿色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> filtered_color(filter_cloud, 0, 255, 0);
viewer->addPointCloud(filter_cloud, filtered_color, "filtered_cloud", v2);
// 设置点大小
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "original_cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "filtered_cloud");
// 添加坐标系
viewer->addCoordinateSystem(0.1);
// 启动可视化
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
}
int main(int argc, char** argv)
{
// 1. 读取点云文件
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in(new pcl::PointCloud<pcl::PointXYZ>());
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out(new pcl::PointCloud<pcl::PointXYZ>());
if (pcl::io::loadPCDFile<pcl::PointXYZ>("palen_noise.pcd", *cloud_in) == -1)
{
PCL_ERROR("Couldn't read the file \n");
return (-1);
}
// 2. 应用局部最大值滤波
applyLocalMaximumFilter(cloud_in, cloud_out, 0.5f); // 设置搜索半径为 1.0
// 3. 打印点云的点数
std::cout << "输入点云个数: " << cloud_in->size() << std::endl;
std::cout << "输出点云个数: " << cloud_out->size() << std::endl;
// 4. 可视化
visualize_cloud(cloud_in, cloud_out);
return 0;
}