PCL_filter模块中各类滤波器目录

  • 一、直通滤波器(PassThrough):用于阈值滤除
    • 1、直通滤波器介绍
    • 2、示例代码
  • 二、体素滤波器(VoxelGrid filter):用于下采样
    • 1、体素滤波器介绍
    • 2、示例代码
  • 三、统计离群滤波器(StatisticalOutlierRemoval filter):用于离群点滤除
    • 1、统计离群滤波器介绍
    • 2、示例代码
  • 四、条件和半径滤波器(Conditional or RadiusOutlier ):用于离群点滤除
    • 1、条件和半径滤波器介绍
    • 2、示例代码
      • 总结:

一、直通滤波器(PassThrough):用于阈值滤除

1、直通滤波器介绍

  直通滤波器(PassThrough),顾名思义就是使用某个阈值直接过滤掉不符合阈值的滤波器。例如有值范围在1到100的十万个数字,直通滤波器设置阈值为<50,则经过直通滤波器过滤后,这十万个数字里所有>=50的数字将被遗弃掉,仅保留满足阈值的所有数字。

2、示例代码

首先,在编辑器中创建一个文件,比如pass .cpp,并将以下内容放入其中,代码分析见注释。

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>int main (){// 原始点云指针pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);// 过滤后的点云指针pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);// 设置点云为无序点云,共5个点cloud->width  = 5;cloud->height = 1;cloud->points.resize (cloud->width * cloud->height);for (auto& point: *cloud) //随机生成点坐标{point.x = 1024 * rand () / (RAND_MAX + 1.0f);point.y = 1024 * rand () / (RAND_MAX + 1.0f);point.z = 1024 * rand () / (RAND_MAX + 1.0f);}// 输出创建的点std::cerr << "Cloud before filtering: " << std::endl;for (const auto& point: *cloud)std::cerr << "    " << point.x << " "<< point.y << " "<< point.z << std::endl;
/*
* 以下代码创建PassThrough筛选器对象,并设置其参数。
* 过滤器字段名设置为z坐标,
* 接受的间隔值设置为(0.0;1.0)。
*/// 创建过滤器对象pcl::PassThrough<pcl::PointXYZ> pass;pass.setInputCloud (cloud);      // 填入数据pass.setFilterFieldName ("z");   // 设置要过滤的维度名,这里为z向维度pass.setFilterLimits (580.0, 900); // 设置滤波阈值//pass.setFilterLimitsNegative (true);pass.filter (*cloud_filtered);    // 开始滤波// 输出滤波后的点std::cerr << "Cloud after filtering: " << std::endl;for (const auto& point: *cloud_filtered)std::cerr << "    " << point.x << " "<< point.y << " "<< point.z << std::endl;return (0);
}

过滤效果:绿色为阈值内的满足阈值(580,900)的点,红色为被过滤的点。当setFilterLimitsNegative参数设为True时,则选取( Z<580 || Z >900 )内的点云。

二、体素滤波器(VoxelGrid filter):用于下采样

1、体素滤波器介绍

  体素滤波器(VoxelGrid filter),常被用于点云数量的下降,即点云下采样。可类比于图像金字塔下采样。顾名思义,将点云按照空间三维划分体素(空间网格),并使用数学方法将每个体素内的点云替换成一个点,从而减少点云数量。
官方的解释:
  体素下降法:将要展示的VoxelGrid类在输入点云数据上创建一个3D体素网格(将体素网格想象为空间中的一组微型3D盒子)。然后,在每个体素(即3D框)中,所有出现的点将被近似(即下采样)到它们的质心。这种方法比用体素中心逼近它们要慢一些,但它能更准确地表示底层表面。

2、示例代码

首先,下载数据集table_scene_lms400.pcd并将其保存到磁盘某处。我这里由于暂时连不上github,使用他人的效果图替代一下。
将如下代码粘贴到编辑器中,并进行编译。

 #include <iostream>#include <pcl/io/pcd_io.h>#include <pcl/point_types.h>#include <pcl/filters/voxel_grid.h>intmain (){pcl::PCLPointCloud2::Ptr cloud (new pcl::PCLPointCloud2 ());pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2 ());// 创建点云读取器对象pcl::PCDReader reader;// 将下载的pcd文件路径替代以下路径reader.read ("table_scene_lms400.pcd", *cloud); std::cerr << "PointCloud before filtering: " << cloud->width * cloud->height << " data points (" << pcl::getFieldsList (*cloud) << ")." << std::endl;// 创建体素过滤器对象pcl::VoxelGrid<pcl::PCLPointCloud2> sor;sor.setInputCloud (cloud);//LeafSize是体素栅格叶大小参数,每个元素分别表示体素在XYZ方向上的尺寸。单位是m,此处0.01代表一厘米。sor.setLeafSize (0.01f, 0.01f, 0.01f);sor.filter (*cloud_filtered);std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points (" << pcl::getFieldsList (*cloud_filtered) << ")." << std::endl;//创建点云写入器将滤波后的点云写入pcd文件中pcl::PCDWriter writer;writer.write ("table_scene_lms400_downsampled.pcd", *cloud_filtered, Eigen::Vector4f::Zero (), Eigen::Quaternionf::Identity (), false);return (0);
}

滤波效果如下:
体素滤波前:

体素滤波后效果:

三、统计离群滤波器(StatisticalOutlierRemoval filter):用于离群点滤除

1、统计离群滤波器介绍

  统计离群滤波器(StatisticalOutlierRemoval filter)常被用于删除离群点(噪声和杂点),该滤波器使用统计分析技术从点云数据集中去除噪声测量,例如离群值。
  1.1背景:
  激光扫描通常生成不同点密度的点云数据集。此外,测量误差还会导致稀疏的异常值,从而进一步破坏结果。这使得局部点云特征(如表面法线或曲率变化)的估计变得复杂,从而导致错误的值,进而可能导致点云配准失败。其中一些不规则性可以通过对每个点的邻域进行统计分析来解决,并对那些不符合一定标准的点进行修剪。离群点去除方法是基于计算点到邻点的距离在输入数据集中的分布。对于每一个点,计算它到所有相邻点的平均距离。通过假设得到的分布是具有均值和标准差的高斯分布,所有的点,其均值距离在由全局距离均值和标准差定义的区间之外,都可以被认为是离群点,并从数据集中进行修剪。
  下面的图片展示了离群点分析和去除的效果:左边是原始数据集,右边是生成的数据集。该图显示了滤波前后一个点附近的平均k近邻距离。

2、示例代码

  依旧是先从github上下载如下数据集table_scene_lms400_inliers.pcd。然后将如下代码粘贴到编译器中。

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>intmain (){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;// 将下载的pcd文件路径替换以下路径reader.read<pcl::PointXYZ> ("table_scene_lms400.pcd", *cloud);std::cerr << "Cloud before filtering: " << std::endl;std::cerr << *cloud << std::endl;// 创建滤波器对象sorpcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
/* 参数设置:
* 每个点要分析的邻居数设置为50,标准差乘数为1。
* 这意味着,所有到查询点的距离大于1个标准差的点都将被标记为离群值并被删除。
* 输出被计算并存储在cloud_filtered中。
*/sor.setInputCloud (cloud);// 填入点云sor.setMeanK (50);        // 设置均值参数Ksor.setStddevMulThresh (1.0);// 设置sor.filter (*cloud_filtered);std::cerr << "Cloud after filtering: " << std::endl;std::cerr << *cloud_filtered << std::endl;// 将滤波后的点云输出成pcd格式文件pcl::PCDWriter writer;writer.write<pcl::PointXYZ> ("table_scene_lms400_inliers.pcd", *cloud_filtered, false);sor.setNegative (true); // 设置成true,条件就会变成所有到查询点的距离小于1个标准差的点都将被标记为离群值并被删除,留下之前被过滤的那些点。sor.filter (*cloud_filtered);writer.write<pcl::PointXYZ> ("table_scene_lms400_outliers.pcd", *cloud_filtered, false);return (0);
}

四、条件和半径滤波器(Conditional or RadiusOutlier ):用于离群点滤除

1、条件和半径滤波器介绍

  [1]条件滤波器,顾名思义,就是给滤波器一些条件值,可以是一个也可以是多个,使用条件滤波器可以滤除所有不满足条件的点,常用于离群点滤除。
  在示例代码中,我们使用在条件中添加两个比较:大于(GT) 0.0和小于(LT) 0.8。然后使用这个条件构建滤波器。
  [2]半径滤波器,顾名思义,给定指定半径,和半径内最少点数进行滤波,例如满足半径0.8内,点数至少为2,即计算每个点半径范围内的点数,少于该点数则被过滤,常用于离群点滤波。
我们来直接看代码:
  下图可以帮助我们理解RadiusOutlierRemoval过滤器对象的作用。用户指定了一些邻域点,每个索引必须在指定的半径参数内。例如,如果指定了1个邻点,那么只有黄色的点将从PointCloud中删除。如果指定了2个邻点,那么黄色和绿色的点都将从PointCloud中删除。

2、示例代码

 #include <iostream>#include <pcl/point_types.h>#include <pcl/filters/radius_outlier_removal.h>#include <pcl/filters/conditional_removal.h>intmain (int argc, char** argv){if (argc != 2){std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;exit(0);}pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);// 随机生成一些点云数据cloud->width  = 5;cloud->height = 1;cloud->resize (cloud->width * cloud->height);for (auto& point: *cloud){point.x = 1024 * rand () / (RAND_MAX + 1.0f);point.y = 1024 * rand () / (RAND_MAX + 1.0f);point.z = 1024 * rand () / (RAND_MAX + 1.0f);}
// 若用户输入-r则使用半径滤波器滤除点云,设置滤除条件:搜索半径0.8,最少点数2,设置滤除后依旧保持点云的有组织性(保持顺序)if (strcmp(argv[1], "-r") == 0){pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;// 设置滤波参数outrem.setInputCloud(cloud);outrem.setRadiusSearch(0.8);outrem.setMinNeighborsInRadius (2);outrem.setKeepOrganized(true);// 开始滤波器outrem.filter (*cloud_filtered);}// 若用户输入指令-c,则启用条件滤波器。else if (strcmp(argv[1], "-c") == 0){// 创建条件滤波器的“条件”,设置条件为两个“比较”滤波器,“GT”是大于的意思,本例中表示z>0的点;“LT”是小于的意思,本例中表示z<0.8的点。因此该滤波器保留(0<z<0.8)的点。pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond (newpcl::ConditionAnd<pcl::PointXYZ> ());range_cond->addComparison (pcl::FieldComparison<pcl::PointXYZ>::ConstPtr (newpcl::FieldComparison<pcl::PointXYZ> ("z", pcl::ComparisonOps::GT, 0.0)));range_cond->addComparison (pcl::FieldComparison<pcl::PointXYZ>::ConstPtr (newpcl::FieldComparison<pcl::PointXYZ> ("z", pcl::ComparisonOps::LT, 0.8)));// 创建条件滤波器,设置滤除后依旧保持点云的有组织性(保持顺序)pcl::ConditionalRemoval<pcl::PointXYZ> condrem;condrem.setCondition (range_cond);condrem.setInputCloud (cloud);condrem.setKeepOrganized(true);// 开始滤波condrem.filter (*cloud_filtered);}else{std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;exit(0);}std::cerr << "Cloud before filtering: " << std::endl;for (const auto& point: *cloud)std::cerr << "    " << point.x << " "<< point.y << " "<< point.z << std::endl;// display pointcloud after filteringstd::cerr << "Cloud after filtering: " << std::endl;for (const auto& point: *cloud_filtered)std::cerr << "    " << point.x << " "<< point.y << " "<< point.z << std::endl;return (0);
}

总结:

本文章介绍了直通滤波器,体素滤波器,统计离群滤波器,半径滤波器和条件滤波器的概念和示例代码。但是PCL中还有很多滤波器没有介绍,例如任意多边形内部点云滤除CropHull(多用作编写点云后处理软件使用,用于用户界面交互)。这里的介绍都比较简单,详细的介绍和实验结果可以参考前辈的文章。后期所有内容学习完成后,准备自己写一个点云后处理软件,使用QT+PCL实现各种点云后处理功能,到时候会把编写过程写出一篇博文,敬请期待。


【博主简介】
  斯坦福的兔子,男,天津大学机械工程工学硕士。毕业至今从事光学三维成像及点云处理相关工作。因工作中使用的三维处理库为公司内部库,不具有普遍适用性,遂自学开源PCL库及其相关数学知识以备使用。谨此将自学过程与君共享。
博主才疏学浅,尚不具有指导能力,如有问题还请各位在评论处留言供大家共同讨论。
若前辈们有工作机会介绍欢迎私信。

【PCL自学:Filtering】PCL中的各类滤波器介绍与使用 (持续更新)相关推荐

  1. 自学it18大数据笔记-第三阶段Spark-day04——会持续更新……

    笔记为自学时随手记录,如有错误,欢迎指正,不胜感激!现已广州转移至上海,欢迎小伙伴们加qq或微博沟通交流(QQ,微博和博客同名) 笔记分享:自学it18大数据笔记-第三阶段Spark-day04--会 ...

  2. 自学it18大数据笔记-第三阶段Scala-day06——会持续更新……

    笔记为自学时随手记录,如有错误,欢迎指正,不胜感激!现已广州转移至上海,欢迎小伙伴们加qq或微博沟通交流(QQ,微博和博客同名) 笔记分享:自学it18大数据笔记-第三阶段Scala-day06--会 ...

  3. 【推荐】2022年环保行业研究报告产业发展前景市场投资行情分析白皮书(附件中为网盘地址,报告持续更新)

    [推荐]2022年环保行业研究报告产业发展前景市场投资行情分析白皮书(附件中为网盘地址,报告持续更新),每月至少更新一次. 下载地址:https://download.csdn.net/downloa ...

  4. 推荐计算机视觉机器视觉行业研究发展规划前景投资市场行情分析报告(附件中为网盘链接,报告持续更新)

    推荐计算机视觉&机器视觉行业研究发展规划前景投资市场行情分析报告(附件中为网盘链接,报告持续更新),每月更新一次(更新时间为每月月底或月初). 下载地址:https://download.cs ...

  5. 【推荐】2022年新基建研究报告白皮书投资策略产业发展前景市场行情分析(附件中为网盘地址,报告持续更新)

    [推荐]2022年新基建研究报告白皮书投资策略产业发展前景市场行情分析(附件中为网盘地址,报告持续更新),每月至少更新一次. 下载地址:https://download.csdn.net/downlo ...

  6. 【推荐】2022年物流快递行业市场行情分析投资趋势产业发展前景调研究报告(附件中为网盘地址,报告持续更新)

    [推荐]2022年物流快递行业市场行情分析投资趋势产业发展前景调研究报告(附件中为网盘地址,报告持续更新),每月至少更新一次. 下载地址:https://download.csdn.net/downl ...

  7. 【推荐】2022年公用事业行业研究报告产业发展前景市场投资行情分析白皮书(附件中为网盘地址,报告持续更新)

    [推荐]2022年公用事业行业研究报告产业发展前景市场投资行情分析白皮书(附件中为网盘地址,报告持续更新),每月至少更新一次. 下载地址:https://download.csdn.net/downl ...

  8. 【推荐】2022年区块链行业研究报告投资策略产业发展前景市场行情分析(附件中为网盘地址,报告持续更新)

    [推荐]2022年区块链行业研究报告投资策略产业发展前景市场行情分析(附件中为网盘地址,报告持续更新),每月至少更新一次. 下载地址:https://download.csdn.net/downloa ...

  9. 2022年推荐云计算行业研究报告投资策略产业发展前景市场行情分析(附件中为网盘链接,报告持续更新)

    2022年推荐云计算行业研究报告投资策略产业发展前景市场行情分析(附件中为网盘链接,报告持续更新). 下载地址:https://download.csdn.net/download/mengchens ...

最新文章

  1. Linux下安装rabbitmq3.7.8
  2. AC日记——字符串最大跨距 openjudge 1.7 26
  3. cdh 添加jar包_使用maven下载cdh版本的大数据jar包
  4. java知识博客网站(一些配置和学习的记录)
  5. 地图库地之图地图窝_「方舆」秦朝地图及行政区划
  6. Android官方开发文档Training系列课程中文版:手势处理之滚动动画及Scroller
  7. 软件需求分析文档模板_小议管理软件需求分析
  8. mysql-查询二-分组与聚合
  9. 一个项目部署多个节点会导致锁失效么_一文看透 Redis 分布式锁进化史(解读 + 缺陷分析)...
  10. Mian容器中Page分頁
  11. 华林SAP论坛(华林自建的SAP论坛)
  12. 《中国人工智能系列白皮书——智能驾驶》精编
  13. 拼多多API接口,item_search - 按关键字搜索商品
  14. DDN区块链:面向未来,全面发力!
  15. matlab 打包封装,matlab中如何封装打包成exe文件
  16. alsa 添加codec
  17. 基于Springboot+支付宝小程序会员开卡功能的服务端实现总结
  18. 企业防火墙软件的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  19. d如何及为什么探测器
  20. 关于FT232R下载模块,出现“FT232R USB UART”不识别的解决办法

热门文章

  1. mac hdmi 不能调整音量_在Mac上玩塞尔达?BMD视频采集卡 Review
  2. vcruntime140_1.dll下载及安装【vcruntime140_1.dll丢失的解决方法】
  3. P1610 鸿山洞的灯(贪心算法)C++
  4. 豆粕四连跌见顶?系统性风险降低通胀压力大,甲醇05-09季节性反套2022.3.29
  5. 棋牌游戏通用牌型数值化方案
  6. Kali的w3af安装及创建快捷方式的【详细】教程
  7. win10修改文件创建时间
  8. android x8,3英寸高性价比Android手机 索爱X8评测
  9. RV1109_RV1126 EVB开发板环境搭建及使用总结
  10. 地图编辑器开发(五)