2. 点云预处理

任务目标

本案例使用PCL(Point Cloud Library)对激光雷达点云执行统计滤波(StatisticalOutlierRemoval),去除稀疏离群点,提升点云数据质量。输入为包含噪声的原始点云,输出为滤波后的干净点云,并保存为PCD文件以便后续处理。

环境依赖

  • Ubuntu 20.04+ / Windows 10+
  • PCL 1.10+(含pcl_io、pcl_filters模块)
  • CMake 3.10+
  • C++11及以上编译器

关键完整代码

// statistical_filter.cpp
#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) {
    if (argc != 3) {
        std::cerr << "Usage: " << argv[0] << " input.pcd output.pcd" << std::endl;
        return -1;
    }

    // 加载点云
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[1], *cloud) == -1) {
        std::cerr << "Failed to load " << argv[1] << std::endl;
        return -1;
    }
    std::cout << "Input points: " << cloud->size() << std::endl;

    // 统计滤波:每个点的邻域点数 < 50 或距离均值偏差 > 1.0 倍标准差则剔除
    pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
    sor.setInputCloud(cloud);
    sor.setMeanK(50);          // 查询邻域点数
    sor.setStddevMulThresh(1.0); // 标准差倍数阈值
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
    sor.filter(*cloud_filtered);

    std::cout << "Filtered points: " << cloud_filtered->size() << std::endl;

    // 保存结果
    pcl::io::savePCDFileBinary(argv[2], *cloud_filtered);
    std::cout << "Saved to " << argv[2] << 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

# 运行(需准备含噪声的输入PCD文件)
./statistical_filter ../noisy_cloud.pcd ../filtered_cloud.pcd

验证方法

  1. 点数对比:程序输出中Filtered points应明显小于Input points,表明离群点被剔除。
  2. 可视化检查:使用PCL可视化工具或CloudCompare打开filtered_cloud.pcd,观察点云主体结构完整,稀疏飞点消失。
  3. 参数调优:若主体点云被误删,增大setMeanK或setStddevMulThresh;若噪声残留,则减小阈值。

预期输出示例

Input points: 128934
Filtered points: 121567
Saved to ../filtered_cloud.pcd

以上输出仅为逻辑推演示例,实际数值取决于输入点云噪声分布。

常见问题

  • 加载失败:确认PCD文件路径正确且文件为ASCII或二进制格式。
  • 滤波过度:点云主体被大量删除时,应增大setMeanK(如100)或setStddevMulThresh(如2.0)。
  • 滤波不足:仍有明显离群点时,减小setStddevMulThresh至0.5或降低setMeanK。