3. 点云预处理
任务目标
本案例使用PCL(Point Cloud Library)的统计滤波(StatisticalOutlierRemoval)对含噪点云进行去噪处理。通过调整两个关键参数——邻域点数(MeanK)与标准差阈值(StddevMulThresh),观察去噪效果差异,并统计滤波前后的点云数量变化,为后续配准、分割等处理提供干净的数据输入。
环境与依赖
- Ubuntu 20.04+ / Windows 10+,已安装PCL 1.10+及CMake 3.10+
- 输入数据:使用PCL官方示例点云
table_scene_lms400.pcd(含离群噪声),可从PCL测试数据目录获取,或使用任意含离群点的PCD文件
完整实现代码
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <iostream>
int main(int argc, char** argv) {
// 输入输出文件路径
std::string input_file = "table_scene_lms400.pcd";
std::string output_file = "table_scene_filtered.pcd";
if (argc >= 2) input_file = argv[1];
if (argc >= 3) output_file = argv[2];
// 加载点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>(input_file, *cloud) == -1) {
std::cerr << "无法读取文件: " << input_file << std::endl;
return -1;
}
std::cout << "原始点云点数: " << cloud->size() << std::endl;
// 创建统计滤波器
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
sor.setInputCloud(cloud);
sor.setMeanK(30); // 邻域点数
sor.setStddevMulThresh(1.0); // 标准差阈值倍数
sor.filter(*cloud);
std::cout << "滤波后点数: " << cloud->size() << std::endl;
// 保存结果
pcl::io::savePCDFileBinary(output_file, *cloud);
std::cout << "结果已保存至: " << output_file << std::endl;
return 0;
}
CMake配置
cmake_minimum_required(VERSION 3.10)
project(statistical_filter)
find_package(PCL 1.10 REQUIRED COMPONENTS io filters)
add_executable(statistical_filter statistical_filter.cpp)
target_link_libraries(statistical_filter ${PCL_LIBRARIES})
add_definitions(${PCL_DEFINITIONS})
编译与运行
# 编译
mkdir build && cd build
cmake ..
make
# 运行(默认参数 MeanK=30, StddevMulThresh=1.0)
./statistical_filter
# 自定义参数运行(修改源码中setMeanK/setStddevMulThresh值后重新编译)
# 或直接修改源码中的参数值进行对比实验
参数调整与效果评估
为观察参数影响,建议修改源码中setMeanK和setStddevMulThresh的值,分别编译运行并记录输出点数:
- 固定MeanK=30,将StddevMulThresh分别设为0.5、1.0、2.0:阈值越小,被判定为离群点的数量越多,去噪越激进,但可能误删有效边缘点。
- 固定StddevMulThresh=1.0,将MeanK分别设为10、30、50:邻域点数越多,统计估计越稳定,但对局部密度变化更敏感。
验证方法与通过标准
- 数量验证:运行程序后,观察控制台输出的“原始点云点数”与“滤波后点数”。滤波后点数应少于原始点数,且差异量随标准差阈值减小而增大。
- 可视化验证:使用PCL可视化工具或CloudCompare打开原始与滤波后的PCD文件,确认离群散点被移除,主体结构(如桌面与物体表面)保持完整。
- 参数敏感性验证:对比不同参数组合下的输出点数,若StddevMulThresh从2.0降至0.5时点数明显减少,说明滤波效果对参数敏感,符合统计滤波原理。
常见问题
- 滤波后点数反而增多:检查是否误将滤波结果赋值给输入指针(如
cloud),导致二次滤波。本代码中sor.filter(*cloud)直接覆盖原指针,重复运行会叠加效果。 - 主体边缘被过度去除:说明标准差阈值过小(如0.5以下),或邻域点数过少导致统计不稳定。建议先以MeanK=30、阈值1.0为基准,逐步调整。
- 处理速度慢:统计滤波需计算每个点的邻域统计量,点云超过百万点时耗时明显。可先用体素滤波降采样,或增大MeanK减少计算量。