通过 PCL实现 几种 点云滤波 的 方法_pcl 过滤点云_月照银海似蛟龙的博客-程序员秘密

技术标签: PCL  

滤波原因

在获取点云数据时,由于设备精度、操作者经验、环境因素等带来的影响,以及电磁波衍射特性、被测物体表面性质变化和数据拼接配准操作过程中的影响,点云数据中将不可避免将出现一些噪声点。实际应用中,除了这些测量随机误差产生的噪声点之外,由于收到外界干扰,如视线遮挡、障碍物等因素的影响,点云数据中往往存在些离主体点云较远的离群点。

在点云处理流程中,滤波处理作为预处理的第一步,对后续(配准、特征提取、曲面重建)处理影响很大。

PCL中点云滤波模块提供了很多灵活实用的滤波处理算法,如双边滤波、高斯滤波、条件滤波、直通滤波、体素滤波等等。

什么情况下需要滤波呢,有以下几种:

  • 点云数据密度不规则需要平滑
  • 因为遮挡等问题造成离群点需要去除
  • 大量数据需要进行下采样
  • 噪音数据需哟去除

下面通过PCL的库 实现 几种 滤波

PCL中的filters模块及类

pcl_filters模块提供对噪声点和离群点去除的具体实现。filters模块用32个类和5个函数实现了对点云数据进行不同的滤波以达到去除不需要点的目的。

可以打开pcl库下面的filters的文件夹,里面是该模块的各个头文件,在使用某个模块时必须要包含该头文件。
例如:
passthrough.h 直通滤波
voxel_grid.h 体素滤波
statistical_outlier_removal.h 离群点滤波
project_inliers.h 投影滤波
在这里插入图片描述

Code

===========================================================

#include <iostream>
#include <ctime>
#include <pcl/point_types.h>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/passthrough.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/ModelCoefficients.h>
#include <pcl/filters/project_inliers.h>

需要包含的头文件
里面有上面提到的几种滤波的头文件

格外说明的是,在CMakeList.txt文件中要 find_package 下 filters模块,否则会报错的

# 寻找PCL的库
find_package(PCL REQUIRED COMPONENT common io visualization filters)

===========================================================

    //声明一个点云 指针
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);

    //从PCD 中 读取点云
    pcl::io::loadPCDFile ("../wolf.pcd", *cloud);

声明一个点云 指针,然后从PCD 文件中读取

这个点云是从网上找的一个 狼的 点云。 下面的滤波也就从 这 个 上面 演示效果

可以通过 下面指令 看下 原始点云
在这里插入图片描述
这个样子的

===========================================================

直通滤波

直通滤波:对指定的某一纬度 实行 一个 简单 的滤波,即去掉指定范围内部或者外部的点。

    /* 声明 直通滤波 后 的点云 */
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_PassThrough_filtered (new pcl::PointCloud<pcl::PointXYZ>);

    /* 声明直通滤波 的 类实例 */
    pcl::PassThrough< pcl::PointXYZ >  pass;
    /* 设置输入点云 */
    pass.setInputCloud (cloud);
    /* 设置滤波的维度 */
    pass.setFilterFieldName ("z");
    /* 设置滤波的范围 */
    pass.setFilterLimits (-50.0,50.0);
    /* 设置去掉的 是 范围内(true) 还是 范围外(false)   */
    pass.setFilterLimitsNegative (1);
    /* 执行滤波 返回 滤波后 的 点云 */
    pass.filter (*cloud_PassThrough_filtered);

   
    // 显示直通滤波后的点云
    /* 创建显示 类 实例 */
    pcl::visualization::CloudViewer viewer1("Cloud Viewer PassThrough"); 

    /* 显示点云 */
    viewer1.showCloud(cloud_PassThrough_filtered);

        /*持续显示*/
    while (!viewer1.wasStopped ())
    {
    
    }

总结下代码 实现步骤
1、声明直通滤波 的 类实例
2、设置输入点云
3、设置滤波的维度
4、设置滤波的范围
5、设置去掉的 是 范围内(true) 还是 范围外(false)
6、执行滤波 返回 滤波后 的 点云

然后通过显示 来 看下 滤波后的效果
在这里插入图片描述

//将这个改为0  即 去除 范围外 的 点 的效果
 pass.setFilterLimitsNegative (0);

在这里插入图片描述
下半部分被保存

===========================================================

体素滤波

体素滤波是 体素化网格方法实现下采样,即减少点的数量,并同时保持点云的形状特征,在提高配准、曲面重建、形状识别等算法速度中非常实用。

说直白点就是 一个体素 就是一个小的单元,这个单元里面 原始点云有很多点的话会求 这些 点 的 重心点,然后 在这个单元中 多个点就变成了一个点

    /* 声明 体素滤波 后 的点云 */
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_VoxelGrid_filtered (new pcl::PointCloud<pcl::PointXYZ>);

    /* 声明体素滤波 的 类实例 */
    pcl::VoxelGrid<pcl::PointXYZ> sor;
    /* 设置输入点云 */
    sor.setInputCloud (cloud);
    /* 设置体素滤波的参数 */  //10.1 米的立方体
    sor.setLeafSize (10.1f, 10.1f, 10.1f);
    /* 执行滤波 返回 滤波后 的 点云 */
    sor.filter (*cloud_VoxelGrid_filtered);

        // 显示体素滤波后的点云
    /* 创建显示 类 实例 */
    pcl::visualization::CloudViewer viewer2("Cloud Viewer VoxelGrid"); 

    /* 显示点云 */
    viewer1.showCloud(cloud_VoxelGrid_filtered);

        /*持续显示*/
    while (!viewer1.wasStopped ())
    {
    
    }

总结下代码 实现步骤
1、声明体素滤波 的 类实例
2、设置输入点云
3、设置体素滤波的参数
4、执行滤波 返回 滤波后 的 点云

然后通过显示 来 看下 滤波后的效果

滤波前
在这里插入图片描述
滤波后
在这里插入图片描述
可以看到点云稀疏了很多,但是外形没有变化。面部细节少了很多

===========================================================

离群点滤波

顾名思义,就是去掉 离 点云群较远的点。

    /* 声明 离群点滤波 后 的点云 */
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_OutRemove_filtered (new pcl::PointCloud<pcl::PointXYZ>);

    /* 声明 离群点滤波 的 类实例 */
    pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor_OutRemove;
    /* 设置输入点云 */
    sor_OutRemove.setInputCloud (cloud);
    /* 设置在进行统计时考虑查询点邻近点数 */
    sor_OutRemove.setMeanK (30);
    /* 设置判断是否为离群点 的 阈值  设置为1的 话 表示为:如果一个点的距离超过平均距离一个标准差以上则为离群点 */
    sor_OutRemove.setStddevMulThresh (1.0);
     /* 执行滤波 返回 滤波后 的 点云 */
    sor_OutRemove.filter (*cloud_OutRemove_filtered);


    /* 打印滤波前后的点数 */
    std::cout<<"size of clound :"<<cloud->points.size()<<"   size of  outremove "<<cloud_OutRemove_filtered->points.size()<<endl;

总结下代码 实现步骤
1、声明 离群点滤波 的 类实例
2、设置输入点云
3、设置在进行统计时考虑查询点邻近点数
4、设置判断是否为离群点 的 阈值 设置为1的 话 表示为:如果一个点的距离超过平均距离一个标准差以上则为离群点
5、执行滤波 返回 滤波后 的 点云

在这里插入图片描述
滤波前3400个点 ,滤波后2702个点

同样和直通滤波类似,可以设置

pass.setFilterLimitsNegative (0);

来返回被滤掉的离群点

===========================================================

投影滤波

通过使用参数化模型,将点投影到参数化模型上。参数化模型通过一组参数来设定,对于平面来说,形式也就是
ax+by+cz+d = 0
在pcl中有特意存储常见模型系数的数据结构

    /* 声明 投影 滤波 后 的点云 */
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected (new pcl::PointCloud<pcl::PointXYZ>);

    /*定义模型 系数 对象 ,并填充 对应 的数据  如果是 平面 ax+by+cz+d = 0  投影到z平面 即 a、b、d 为0  c为1 */
    pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ());
    coefficients->values.resize (4);
    coefficients->values[0] = 0;
    coefficients->values[1] = 0;
    coefficients->values[2] = 1;
    coefficients->values[3] = 0;

    /* 声明 投影滤波 的 类实例  */
    pcl::ProjectInliers<pcl::PointXYZ> proj;
    /* 设置参数化模型的类型 */
    proj.setModelType (pcl::SACMODEL_PLANE);
    /* 设置输入点云 */
    proj.setInputCloud (cloud);
    /* 设置上面填充完的模型 */
    proj.setModelCoefficients (coefficients);
    /*  执行滤波 返回 滤波后 的 点云 */
    proj.filter (*cloud_projected);

总结下代码 实现步骤
1、定义模型 系数 对象 ,并填充 对应 的数据
2、声明 投影滤波 的 类实例
3、设置参数化模型的类型
4、设置输入点云
5、设置上面填充完的模型
6、执行滤波 返回 滤波后 的 点云

上面的模型为平面 模型 方程即为 ax+by+cz+d = 0
设置参数 为 a=b=d = 0 c=1
即投影到z平面

下面时投影的效果
在这里插入图片描述
在这里插入图片描述
被压平了

===========================================================

Result

原始点云
在这里插入图片描述
直通滤波在这里插入图片描述
在这里插入图片描述
体素滤波
在这里插入图片描述
投影滤波
在这里插入图片描述
在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_32761549/article/details/118147255

智能推荐

如何画好一张架构图?_阿里开发者的博客-程序员秘密

简介:&nbsp;架构图是什么?为什么要画架构图?如何画?有哪些方法?本文从架构的定义说起,分享阿里文娱高级技术专家箫逸关于画架构图多年的经验总结,并对抽象这一概念进行了深入地讨论。较长,同学们可收藏后再看。什么是架构图?如何画好一张架构图,要做好这件事情首先要回答的就是什么是架构图。我们日常工作中经常能看到各种各样的架构图,而且经常会发现大家对架构图的理解各有侧重。深入追究到这个问题,可能一下子还很难有一个具象的定义,如果我们把这个问题进行拆分(如下图)理解起来就会容易一点。架构图 = 架构 + 图

春招总结(作业帮、华为、腾讯、美团、京东面经)_回廊识路的博客-程序员秘密

春招总结(作业帮、华为、腾讯、美团、京东面经)在WP上发博客没人看( ̄▽ ̄)”,最终还是选择CSDN上总结一下自己春招的经历。问题整理得不太及时,但已经是尽力回想了,希望能帮到需要的童鞋。作业帮(一面挂)笔试选择填空计网、操作系统、数据结构基础知识(排序算法的时空复杂度)、记得选择题最后一题是给了一段Linux下C的多进程/多线程代码问输出是怎样的。编程题实...

GOOGLE笔试题(10.15电子科大)_dingqiangzhen9665的博客-程序员秘密

两个教室,应该有个50、60号人吧。不求他,过来长长见识,看看Google笔试都是些神马神题。然后,就彻彻底底的打酱油了。90min完成10个选择题2个编程题1个算法设计题。尽量还原原题,但记性不好大家勿怪。选择题:1.比较几个速率:a.闪存速率、b.100M以太网速率、c.火车运100TB内容以100km/h从北京到天津(全长100公里)、d. MP3的PCI总线读到播放器...

使你的C/C++代码支持Unicode_c++单个文件打开_unicode宏_wzxiaodu的博客-程序员秘密

转自:https://blog.csdn.net/akof1314/article/details/5060971本文摘自I18nGuy主页的一篇内容,原文地址:http://www.i18nguy.com/unicode/c-unicode.zh-CN.html文档在线看:http://www.docin.com/p-37841375.html这份文档简要的说明了如何修改你的C/C++代码使之支持Unicode。在这里并不准备解释太多相关的技术细节并且我得假定你已经基本熟悉Micros..

stm32f0串口 DMA 空闲中断接收——基于HAL库(代码篇)_hal库串口中断接收数据判断代码_噗噗bug的博客-程序员秘密

一、STM32CubeMX开发1.1 新建工程file -&gt; new project选择芯片-&gt; stm32 core内核 stm32 series 系列 stm32 line stm32 package选择芯片根据自身需求去选择,目前该项目是stm32f0系列 stm32 core内核 ...

hdu 2412 Party at Hali-Bula(树形DP)_AC_way的博客-程序员秘密

Party at Hali-BulaTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1860    Accepted Submission(s): 649Problem DescriptionDear Con

随便推点

Spark>提交Yarn集群报错异常_BigMoM1573的博客-程序员秘密

文章目录如果整合Yarn报错或无法查看log需做如下操作配置历史日志服务器异常二:如果整合Yarn报错或无法查看log需做如下操作1.修改hadoop的yarn-site.xmlvim /export/servers/hadoop/etc/hadoop/yarn-site.xml &lt;property&gt; &lt;name&gt;yarn.res...

程序猿大佬怒了_xudc的博客-程序员秘密

这两天开始,有一个开源项目火了,源于996的摧残模式,大佬愤愤弄了个网站,控诉这摧残人身心的工作模式。996工作制,意为每天早 9 点到岗,一直工作到晚上 9 点。每周工作 6 天。“996”工作制的周工作时间为最低 60 小时。网站如下:https://996.icu/#/zh_CN项目已经开源到GitHub上,并迅速引起了中国程序员的共鸣,以及外国程序友人的关注。GitHub地...

java中statfs_StatFs Class (Android.OS) | Microsoft Docs_tianran li的博客-程序员秘密

StatFs ClassDefinitionNamespace:Assembly:Mono.Android.dllRetrieve overall information about the space on a filesystem.In this article[Android.Runtime.Register("android/os/StatFs", ApiSince=1, DoNotGen...

信息安全的密码学基于sagemath的python实现(RES、AES、RSA、ECC、哈希算法以及数字签名)_sagemath密码学_Life is a joke的博客-程序员秘密

Mono-alphabetic Cipheralpha="abcdefghijklmnopqrstuvwxyz"def is_alpha_char(c):return (c.lower() in alpha)def get_alpha_index(c):return alpha.index(c.lower())def get_key_index(c,key): return key.index(c.upper())def encrypt_ma(k, plaintext): cip

Extjs4表格宽度和高度自适应_extjs 固定表格宽度_菲雨雾歌的博客-程序员秘密

开发Extjs的时候难免会遇到宽度和高度不合浏览器的情况,这种情况导致的问题是:1.如果表格数据多了以后,右侧滚动条不出现。2.如果表格较长的话,无论页面如何缩放,都没办法看全整个表格。作者使用的情况是在一个tabPanel里放一个gridPanel,想让这个grid随着tabPanel的变化而自动适应窗口宽度和高度。在Extjs4中,经过前段时间的摸索,走了很多弯路。网上有些人说使用

HDOJ-三部曲一(搜索、数学)-1003-Curling 2.0_weixin_30651273的博客-程序员秘密

Curling 2.0Time Limit : 2000/1000ms (Java/Other)Memory Limit : 131072/65536K (Java/Other)Total Submission(s) : 22Accepted Submission(s) : 10Problem DescriptionOn Planet MM-21, after th...

推荐文章

热门文章

相关标签