4. 点云预处理

任务目标

本案例实现点云半径滤波(Radius Outlier Removal):对输入点云中每个点,统计其指定半径邻域内的邻居数量,若邻居数低于阈值则判定为稀疏离群点并剔除,从而保留密集区域的有效点。输入采用PCD格式,输出为滤波后的PCD文件,并在终端打印剔除前后点数。

环境依赖

需要 PCL 1.10+(含pcl_io、pcl_filters模块)与CMake 3.10+。若尚未安装PCL,在Ubuntu下执行:

sudo apt install libpcl-dev

关键完整代码

创建文件 radius_filter.cpp:

#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <iostream>

int main(int argc, char** argv) {
    if (argc != 5) {
        std::cerr << "用法: " << argv[0]
                  << " <输入.pcd> <输出.pcd> <半径> <最小邻居数>\n";
        return -1;
    }

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    if (pcl::io::loadPCDFile(argv[1], *cloud) == -1) {
        std::cerr << "无法读取文件: " << argv[1] << "\n";
        return -1;
    }
    std::cout << "输入点数: " << cloud->size() << "\n";

    float radius = std::stof(argv[3]);
    int min_neighbors = std::stoi(argv[4]);

    pcl::RadiusOutlierRemoval<pcl::PointXYZ> filter;
    filter.setInputCloud(cloud);
    filter.setRadiusSearch(radius);
    filter.setMinNeighborsInRadius(min_neighbors);
    filter.filter(*cloud);

    std::cout << "输出点数: " << cloud->size() << "\n";
    pcl::io::savePCDFileBinary(argv[2], *cloud);
    std::cout << "已保存: " << argv[2] << "\n";
    return 0;
}

创建 CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(radius_filter)
find_package(PCL 1.10 REQUIRED COMPONENTS io filters)
add_executable(radius_filter radius_filter.cpp)
target_link_libraries(radius_filter ${PCL_LIBRARIES})
add_definitions(${PCL_DEFINITIONS})

编译与运行

mkdir build && cd build
cmake ..
make
./radius_filter ../input.pcd ../output.pcd 0.05 5

其中 0.05 为搜索半径(米),5 为最小邻居数阈值。若没有现成PCD文件,可用以下命令生成带噪声的测试点云(需安装 pcl-tools):

sudo apt install pcl-tools
# 生成10000个均匀随机点作为背景噪声
pcl_random_cloud -n 10000 -d 0.1 -o noise.pcd
# 生成一个密集球面点云(半径0.02,约2000点)
pcl_random_cloud -n 2000 -d 0.02 -o dense.pcd
# 合并两者(需写一个简单拼接程序,或直接使用两个文件分别测试)

验证方法

运行程序后观察终端输出:输出点数应明显小于输入点数(稀疏点被剔除)。用PCL可视化工具检查结果:

pcl_viewer output.pcd

通过标准:密集球面区域点云完整保留,周围稀疏孤立点被清除。若输入为纯均匀随机点(无密集结构),则输出点数应接近0,因为每个点邻域内邻居数极少,均低于阈值。

参数调优建议

  • 半径:设为点云平均点间距的2~3倍。点间距越小,半径应越小。
  • 最小邻居数:通常取5~10。若密集区域点密度高,可适当增大;若需保留较稀疏的有效结构,则减小该值。