PCL条件滤波

简介

本篇笔记记录了PCL库条件滤波的使用。在上一篇笔记PCL直通滤波中介绍了PCL的直通滤波方法。直通滤波方法比较简单粗暴,直接“一刀切”的思想对某个坐标轴范围剔除。这在简单的场景会比较简单有效,但一旦涉及稍稍复杂一点点的点云剔除直通滤波用起来就没那么方便顺手了,因为直通滤波一次只能对某个坐标轴的范围进行滤波,假如想限制两个轴以上的范围直通滤波就无能为力了。

而条件滤波(condition removal filter)正好可以解决这个问题,条件滤波相比于直通滤波优点就是一次可以对多个轴的范围进行划定限制。允许自由地添加和组合xyz三个坐标轴方向的范围限制,相比与直通滤波的“一刀切”剔除点云的方法,条件滤波则是你想怎么切就怎么切,切几刀都行。所以可以把条件滤波看作一个加强版的,可自定义的直通滤波看待。下面直接放出使用示例代码:

代码

#include <iostream>
#include <random>

#include "pcl/point_types.h"
#include "pcl/filters/conditional_removal.h"
#include "pcl/visualization/pcl_visualizer.h"

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>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_removed(new pcl::PointCloud<pcl::PointXYZ>);

//step1: 创建点云数据
std::random_device rd;
std::default_random_engine random(rd());
std::uniform_real_distribution&lt;float&gt; dis(0.0f, 3.0f);

for (int i = 0; i &lt; 3000; ++i)
{
    float x = dis(random);
    float y = dis(random);
    float z = dis(random);
    cloud-&gt;points.push_back({ x, y, z });
}

//step2: 创建条件滤波对象
pcl::ConditionalRemoval&lt;pcl::PointXYZ&gt; conditional_removal;

//step3: 设置条件滤波参数

//条件与
//保留点云xyz坐标都在[1,2]之内的点
pcl::ConditionAnd&lt;pcl::PointXYZ&gt;::Ptr condition_add(new pcl::ConditionAnd&lt;pcl::PointXYZ&gt;());
condition_add-&gt;addComparison(pcl::FieldComparison&lt;pcl::PointXYZ&gt;::ConstPtr(new pcl::FieldComparison&lt;pcl::PointXYZ&gt;(&quot;z&quot;, pcl::ComparisonOps::GE, 1.0)));
condition_add-&gt;addComparison(pcl::FieldComparison&lt;pcl::PointXYZ&gt;::ConstPtr(new pcl::FieldComparison&lt;pcl::PointXYZ&gt;(&quot;z&quot;, pcl::ComparisonOps::LE, 2.0)));
condition_add-&gt;addComparison(pcl::FieldComparison&lt;pcl::PointXYZ&gt;::ConstPtr(new pcl::FieldComparison&lt;pcl::PointXYZ&gt;(&quot;y&quot;, pcl::ComparisonOps::GE, 1.0)));
condition_add-&gt;addComparison(pcl::FieldComparison&lt;pcl::PointXYZ&gt;::ConstPtr(new pcl::FieldComparison&lt;pcl::PointXYZ&gt;(&quot;y&quot;, pcl::ComparisonOps::LE, 2.0)));
condition_add-&gt;addComparison(pcl::FieldComparison&lt;pcl::PointXYZ&gt;::ConstPtr(new pcl::FieldComparison&lt;pcl::PointXYZ&gt;(&quot;x&quot;, pcl::ComparisonOps::GE, 1.0)));
condition_add-&gt;addComparison(pcl::FieldComparison&lt;pcl::PointXYZ&gt;::ConstPtr(new pcl::FieldComparison&lt;pcl::PointXYZ&gt;(&quot;x&quot;, pcl::ComparisonOps::LE, 2.0)));

//条件或
pcl::ConditionOr&lt;pcl::PointXYZ&gt;::Ptr condition_or(new pcl::ConditionOr&lt;pcl::PointXYZ&gt;());
condition_or-&gt;addComparison(pcl::FieldComparison&lt;pcl::PointXYZ&gt;::ConstPtr(new pcl::FieldComparison&lt;pcl::PointXYZ&gt;(&quot;z&quot;, pcl::ComparisonOps::GE, 2)));
condition_or-&gt;addComparison(pcl::FieldComparison&lt;pcl::PointXYZ&gt;::ConstPtr(new pcl::FieldComparison&lt;pcl::PointXYZ&gt;(&quot;x&quot;, pcl::ComparisonOps::GE, 1.5)));

//condition_add-&gt;addCondition(condition_or);
condition_or-&gt;addCondition(condition_add);
 
conditional_removal.setCondition(condition_or);
conditional_removal.setInputCloud(cloud);


//step4: 执行滤波处理
conditional_removal.filter(*cloud_filtered);

//step5: 可视化滤波结果
pcl::visualization::PCLVisualizer viewer(&quot;pcl condition removal filter&quot;);
pcl::visualization::PointCloudColorHandlerCustom&lt;pcl::PointXYZ&gt; cloud_handler(cloud, 255, 0, 0);
viewer.addPointCloud(cloud, cloud_handler, &quot;cloud&quot;);

pcl::visualization::PointCloudColorHandlerCustom&lt;pcl::PointXYZ&gt; filtered_handler(cloud_filtered, 0, 255, 0);
viewer.addPointCloud(cloud_filtered, filtered_handler, &quot;cloud_filtered&quot;);

viewer.addCoordinateSystem(1);

while (!viewer.wasStopped())
{
    viewer.spinOnce();
}
viewer.close();

return 0;

}

说明

流程步骤在代码中注释已经简单说明了,这里就几个点做一下补充。

  • api调用流程为:创建滤波对象,创建条件对象(可以是and型或者or型,或者合并两者),设置条件,滤波
  • 条件对象添加条件的格式为
condition_add->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>(“z”, pcl::ComparisonOps::GE, 1.0)));

参数z表示设置z轴的范围条件,GE,1.0是 greater equal, 即表示z轴要大于等于1.0。其他类似还有

pcl::ComparisonOps::LE //小于等于
pcl::ComparisonOps::GT //大于
pcl::ComparisonOps::LT //小于
pcl::ComparisonOps::EQ //相等
  • 设置条件

setCondition可以值用ConditionAnd或者ConditionOr条件对象。

只用ConditionAnd测试

conditional_removal.setCondition(condition_add);

pcl-condition-removal-filter.png

只用ConditionOr测试

conditional_removal.setCondition(condition_or);

condition_or_merge_condition_add.png
也可以将ConditionAnd合并到ConditionOr后设置ConditionOr,反过来也可以将ConditionOr合并到ConditionAnd后设置ConditionAnd,但需要注意的是添加的顺序不一样,组合成的条件结果是不一样的,这个与编程里边&&、||逻辑与或的短路原理是一样的。

ConditionAnd合并到ConditionOr后设置ConditionOr

condition_or->addCondition(condition_add);
conditional_removal.setCondition(condition_or);

condition_or_merge_condition_add.png
此时合并遵循||或的逻辑,所以效果与单独设置ConditionOr是一样的

ConditionOr合并到ConditionAnd后设置ConditionAnd

condition_add->addCondition(condition_or);
conditional_removal.setCondition(condition_add);

condition_add_merge_condition_or.png

此时合并遵循&&与的逻辑,所以效果与单独设置ConditionAnd是一样的


本文由芒果浩明发布,转载请注明出处。
本文链接:https://mangoroom.cn/algorithm/condition-removal-filter-of-pcl.html


### PCL库中的滤波算法实现与应用 PCL(Point Cloud Library)是一个开源项目,专注于提供高效、易用的点云处理工具集。其中,滤波模块是其核心功能之一,用于去除点云数据中的噪声并优化后续处理效果[^1]。 #### 1. 噪声点的影响及其重要性 在实际场景中,通过非接触法测量设备采集到的点云数据通常会受到多种因素干扰,例如设备精度不足、环境光线变化以及被测物体表面特性差异等。这些干扰会在点云数据中引入大量噪声点,从而显著降低后续操作的质量,比如点云拼接和曲面重构的效果。因此,在进一步分析之前对点云进行去噪处理显得尤为重要。 #### 2. 主要滤波算法介绍 PCL 提供了丰富的滤波方法来应对不同类型的噪声问题: - **体素网格滤波 (Voxel Grid)** 这是一种下采样技术,能够有效减少点云密度而不丢失整体结构特征。它将三维空间划分为若干个小立方体(即体素),并对每个体素内的点取平均值作为代表点。以下是其实现代码示例: ```cpp pcl::PointCloud<pcl::PointXYZ>::Ptr filtered(new pcl::PointCloud<pcl::PointXYZ>); pcl::VoxelGrid<pcl::PointXYZ> sor; sor.setInputCloud(cloud); sor.setLeafSize(0.01f, 0.01f, 0.01f); // 设置体素大小为 1 cm³ sor.filter(*filtered); ``` - **统计异常值移除 (Statistical Outlier Removal)** 统计学方法可以识别偏离正常分布范围的数据点,并将其标记为离群点予以删除。这种方法特别适合于处理局部密集区域中存在的孤立噪声点。 ```cpp pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor; sor.setInputCloud(cloud); sor.setMeanK(50); // 考虑邻域内最近的 50 个点 sor.setStddevMulThresh(1.0); // 设定标准差倍数阈值 sor.filter(*filtered); ``` - **双边滤波 (Bilateral Filtering)** 双边滤波能够在平滑点云的同时保留边缘细节,适用于需要保持几何形状的应用场合。 ```cpp pcl::FastBilateralFilter<pcl::PointXYZRGB> bilateral_filter; bilateral_filter.setInputCloud(cloud); bilateral_filter.setSigmaS(5.0f); // 空间核宽度参数 bilateral_filter.setSigmaR(0.05f); // 颜色权重参数 bilateral_filter.filter(*filtered); ``` - **高斯滤波 (Gaussian Filter)** 对每一个点计算加权平均值以达到模糊化目的,有助于消除高频噪音成分。 ```cpp pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne; pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>()); ne.setInputCloud(cloud); ne.setSearchMethod(tree); ne.setRadiusSearch(0.03); // 定义搜索半径 pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>()); ne.compute(*normals); ``` #### 3. 应用实例 上述提到的各种滤波器可以根据具体需求组合使用,形成完整的预处理流程。例如先采用 Voxel Grid 减少冗余信息量,再利用 Statistical Outlier Removal 清理掉稀疏部分存在的杂散点;或者针对彩色模型选用 Fast Bilateral Smoothing 来维持纹理边界清晰度等^。 总之,合理选择合适的滤波策略对于提升最终成果至关重要。开发者应深入理解每种算法的工作机制及其适用条件,以便更好地服务于特定应用场景下的目标达成。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值