点云库PCL学习笔记 -- 点云滤波Filtering -- 3.StatisticalOutlierRemoval 统计滤波器
StatisticalOutlierRemoval 统计滤波器相关简介
激光扫描通常会产生密度不均匀的点云数据集。另外,测量中的误差会产生稀疏的离群点,使效果更糟。估计局部点云特征(例如采样点出的法向量或者曲率变化率)的运算很复杂,这会导致错误的数值,反过来有可能导致点云的配准等后期处理失败。
以下方法可以解决其中部分问题:对每个点的邻域进行一个统计分析,并修剪掉那些不符合一定标准的点。我们的稀疏离群点一处方法基于输入数据中对点到临近点的距离分布的计算。对每个点,我们计算它到它的所有临近点的平均距离。假设得到的结果是一个高斯分布,其形状由均值和标准差决定,平均距离在标准范围(由全局平均值和方差定义)之外的点,可以被定义为离群点并可从数据集中去除掉。
- 下图展示了稀疏离群点分析和移除效果
- 左1图为原始数据集,左2图为处理结果;
- 右图展示了处理签和处理后,一个点邻域范围内的k近邻邻域平均距离。
1. StatisticalOutlierRemoval 统计滤波器代码
StatisticalOutlierRemoval 统计滤波器代码statistical_removal.cpp
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h> //统计滤波类头文件
int
main (int argc, char** argv)
{
//定义并实例化一个PointCloud指针对象,并用读取文件数据点集赋值给它
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
//点云读取对象
pcl::PCDReader reader;
reader.read<pcl::PointXYZ> ("table_scene_lms400.pcd", *cloud); //读取点云文件中的数据到 cloud 对象,table_scene_lms400.pcd 文件与该cpp文件在同一级目录下
//打印点云数据的相关信息
std::cerr << "Cloud before filtering: " << std::endl;
std::cerr << *cloud << std::endl;
//创建 StatisticalOutlierRemoval 统计滤波器
//对每个点分析的临近点的个数设置为50,并将标准差的倍数设置为 1.0 这意味着如果一个点的距离超出了平均距离一个标准差以上,则该点被标记为离群点,并将它移除,存储起来
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor; //创建 StatisticalOutlierRemoval 滤波对象
sor.setInputCloud (cloud); //设置输入点云
sor.setMeanK (50); //设置在进行统计时考虑查询点临近点数,对每个点分析的临近点的个数设置为50
sor.setStddevMulThresh (1.0); //设置判断是否为离群点的阈值,将标准差的倍数设置为 1.0
sor.filter (*cloud_filtered); //执行完滤波处理保存数据点云到 cloud_filtered
//打印滤波完后的点云数据信息
std::cerr << "Cloud after filtering: " << std::endl;
std::cerr << *cloud_filtered << std::endl;
//将滤波后,保存的点云写入 table_scene_lms400_inliers.pcd 文件
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ> ("table_scene_lms400_inliers.pcd", *cloud_filtered, false);
//将滤波后,被过滤的点云写入 table_scene_lms400_outliers.pcd 文件
sor.setNegative (true); // true:滤波结果取反,被过滤掉的点云数据
sor.filter (*cloud_filtered);
writer.write<pcl::PointXYZ> ("table_scene_lms400_outliers.pcd", *cloud_filtered, false);
return (0);
}
2. 编译文件
设置编译文件CMakeLists.txt
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(statistical_removal)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (statistical_removal statistical_removal.cpp)
target_link_libraries (statistical_removal ${PCL_LIBRARIES})
编译
mkdir build
cd build/
cmake ..
make
3. 测试
执行程序
cd ..
./build/statistical_removal
结果如下:
-
未开始滤波时,工程文件的目录如下所示。
目录中的table_scene_lms400.pcd
原始文件与statistical_removal.cpp
文件在同一级目录下。
使用pcl_viewer table_scene_lms400.pcd
查看table_scene_lms400.pcd
文件,如下
可以很清楚的看到,该点云文件的离群点数量相对比较多。
-
开始执行程序后
相关的输出信息
文件目录变化如下所示,程序运行完成后会生成一个table_scene_lms400_inliers.pcd
保存的点云文件和一个table_scene_lms400_outliers.pcd
保存的点云文件,这两个文件为通过StatisticalOutlierRemoval 统计滤波器统计滤波后的文件。
-
使用
pcl_viewer table_scene_lms400_inliers.pcd
查看table_scene_lms400_inliers.pcd
文件,如下所示:
可以很清楚的看到,该点云文件相比之前的原始数据文件离群点少了很多。
-
使用
pcl_viewer table_scene_lms400_outliers.pcd
查看table_scene_lms400_outliers.pcd
文件,如下所示:
该图为由 StatisticalOutlierRemoval 统计滤波器过滤筛选掉的离群点。
两张图的相对比较如下。