统计滤波器:
统计滤波器主要用于去除明显离群点。 离群点特征在空间中分布稀疏。定义某处点云小于某个密度,既点云无效。计算每个点到其最近的k个点平均距离。则点云中所有点的距离应构成高斯分布。根据给定均值与方差,可剔除方差之外的点。
对于图中那些离点云规模较聚集的区域,简称为离群点,统计滤波对这些离群点的处理比较好。
在官方文档里有下面这张图片,可以看出统计滤波器对离群点的处理效果还是比较好的。
#include <iostream>
#include <pcl/io/pcd_io.h>//pcd读写类相关头文件
#include <pcl/point_types.h>//支持点类型头文件
#include <pcl/filters/statistical_outlier_removal.h>//统计滤波器支持头文件
#include <pcl/visualization/cloud_viewer.h>//可视化
#include <pcl/io/io.h>//输入输出头文件
#include <pcl/visualization/pcl_visualizer.h> //PCL可视化的头文件
boost::shared_ptr<pcl::visualization::PCLVisualizer> simpleVis(pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloud)//创建boost shared_ptr共享指针
{
//创建3D窗口并添加点云
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));//窗口显示
viewer->setBackgroundColor(135, 206, 250);//设置背景颜色为淡蓝色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud, 190, 32, 230);//设置点云颜色为粉色
viewer->addPointCloud<pcl::PointXYZ>(cloud, single_color, "sample cloud");//将点云颜色信息添加显示
//viewer->addPointCloud<pcl::PointXYZ>(cloud, "sample cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud");//设置点云点的大小
viewer->addCoordinateSystem(1.0);//添加坐标系
viewer->initCameraParameters();//设置照相机参数,使用户从默认的角度和方向观察点云
return (viewer);//返回viewer
}
int main(int argc, char** argv)
{
pcl::PCLPointCloud2::Ptr cloud(new pcl::PCLPointCloud2());
pcl::PCLPointCloud2::Ptr cloud_filtered(new pcl::PCLPointCloud2());
pcl::PointCloud <pcl::PointXYZ>::Ptr cloudxyz(new pcl::PointCloud<pcl::PointXYZ>);//创建cloudxyz指针
// 填入点云数据
pcl::PCDReader reader;//pcd文件读操作
// 把路径改为自己存放文件的路径
reader.read("D:\\pclcode\\filter\\statistical_removal\\source\\table_scene_lms400.pcd", *cloud);//读取文件夹中的点云文件
std::cerr << "Cloud before filtering: " << cloud->width * cloud->height
<< " data points (" << pcl::getFieldsList(*cloud) << ")." << endl;//显示滤波前点云文件的总点数
// 创建滤波器对象
pcl::StatisticalOutlierRemoval<pcl::PCLPointCloud2> sor;//创建统计滤波器对象
sor.setInputCloud(cloud);//色湖之输入点云
sor.setMeanK(50);//设置考虑查询点临近个数
//sor.setMeanK(100);//设置考虑查询点临近个数
sor.setStddevMulThresh(1.0);//设置判断是否为离群点的阈值
sor.filter(*cloud_filtered);//执行滤波,并将结果保存在clloud_filterd
std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height
<< " data points (" << pcl::getFieldsList(*cloud_filtered) << ")." << endl;//输出滤波后的点云总点数
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;//创建指针
//pcl::fromPCLPointCloud2(*cloud, *cloudxyz);//显示滤波前的点云
pcl::fromPCLPointCloud2(*cloud_filtered, *cloudxyz);//显示滤波后的点云
viewer = simpleVis(cloudxyz);
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
system("pause");
return (0);
}
//sor.setMeanK(50);//设置考虑查询点临近个数
//Cloud before filtering : 460400 data points(x y z intensity distance sid).
//PointCloud after filtering : 451474 data points(x y z intensity distance sid).
//sor.setMeanK(100);//设置考虑查询点临近个数
//Cloud before filtering : 460400 data points(x y z intensity distance sid).
//PointCloud after filtering : 447507 data points(x y z intensity distance sid).
CmakeLists文件:
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})
原始点云文件:
sor.setMeanK(50);//设置考虑查询点临近个数50
执行效果:
sor.setMeanK(100);//设置考虑查询点临近个数100
执行效果:
#include <iostream>
#include <pcl/point_types.h>//pcl支持点类型头文件
#include <pcl/point_cloud.h>//点云头文件
#include <pcl/io/pcd_io.h>//pcd读写类输入输出头文件
#include <pcl/visualization/pcl_visualizer.h>//可视化头文件
#include <pcl/filters/statistical_outlier_removal.h>//统计滤波器头文件
using namespace std;
int main(int argc,char **argv)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile("D:\\pclcode\\filter\\statistical_removal\\source\\scan_010.pcd", *cloud) == -1)//点云文件读取
{
cout << "Could not read the point cloud file scan_010.pcd \n";
system("pause");
return (-1);
}
cout << "原始点云总个数:" << cloud->size() << endl;//输出原始点云的总点数
// 定义滤波器
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;//创建统计滤波器对象
sor.setInputCloud(cloud);//设置输入点云
sor.setMeanK(50); //设置在进行统计时考虑查询点邻近点数
//sor.setMeanK(100); //设置在进行统计时考虑查询点邻近点数100
sor.setStddevMulThresh(1.0); //设置判断是否为离群点的阈值,如果一个点的距离超出平均距离一个标准差以上,则该点被标记为离群点,并将被移除。
//sor.setStddevMulThresh(2.0);//设置判断是否为离群点的阈值,如果一个点的距离超出平均距离一个标准差以上,则该点被标记为离群点,并将被移除
sor.filter(*cloud_filtered);//执行滤波,并将结果储存在cloud_filtered中
//显示点云
pcl::visualization::PCLVisualizer viewer("点云3D可视化");//可视化窗口
cout << "统计滤波之后点云的个数:" << cloud_filtered->size() << endl;//统计滤波后点云文件的总点数
int v1(0);//左边第一个窗口
viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v1);//xmin, ymin, xmax, ymax,取值范围0-1
viewer.setBackgroundColor(0, 0, 0, v1);//设置背景为黑色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> green0(cloud, 0, 225, 0);//设置点云显示为绿色
viewer.addPointCloud(cloud, green0, "cloud", v1);//添加点云
int v2(0);//右边第二个窗口
viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2);//xmin, ymin, xmax, ymax,取值范围0-1
viewer.setBackgroundColor(0.3, 0.3, 0.3, v2);//设置背景颜色为灰色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> green1(cloud_filtered, 0, 225, 0);//设置点云显示为绿色
viewer.addPointCloud(cloud_filtered, green1, "cloud_filtered", v2);//添加点云
while (!viewer.wasStopped()) {
viewer.spinOnce(100);
}
system("pause");
return 0;
}
//sor.setMeanK(50);
//sor.setStddevMulThresh(1.0);
//原始点云总个数:1716575
//sor.setMeanK(50);
//sor.setStddevMulThresh(2.0);
//统计滤波之后点云的个数:1641517
//原始点云总个数:1716575
//统计滤波之后点云的个数:1685130
CmakeLists文件:(同上)
//sor.setStddevMulThresh(1.0);
设置阈值为1的效果:
//sor.setStddevMulThresh(2.0);
设置阈值为2的效果: