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。若密集区域点密度高,可适当增大;若需保留较稀疏的有效结构,则减小该值。