PCL 点云统计滤波

news2024/11/26 20:25:59

目录

一、概述

1.1原理

1.2实现步骤

1.3应用场景

二、代码实现

2.1关键函数

2.1.1 统计滤波实现

2.1.2 可视化函数

2.2完整代码

三、实现效果


PCL点云算法汇总及实战案例汇总的目录地址链接:

PCL点云算法与项目实战案例汇总(长期更新)


一、概述

        统计滤波(Statistical Outlier Removal, SOR) 是一种常用的点云去噪方法。统计滤波通过分析点云中每个点的邻域信息,计算其与邻域内其他点的距离平均值,并将与邻居点的距离过大的点(离群点)去除。这种方法在保留点云主要结构的同时,可以有效地去除孤立点或噪声点。

1.1原理

        统计滤波的基本思想是:对于每个点,计算它的邻域中其他点的平均距离,判断这个点与其邻域中其他点的距离是否显著偏离。如果距离偏离较大,则认为该点是噪声点或离群点,将其剔除。

过滤步骤:

  1. 计算每个点的邻居点的距离平均值。
  2. 将这些平均值与预定的标准偏差范围进行比较。
  3. 如果某点的平均距离超出设定的阈值范围,则认为该点为离群点,剔除该点。

1.2实现步骤

  1. 读取点云数据。
  2. 设置统计滤波器的参数,包括邻居数量和标准偏差阈值。
  3. 应用统计滤波,生成过滤后的点云。
  4. 可视化原始点云和过滤后的点云。

1.3应用场景

  1. 去除噪声点:有效地去除由于传感器噪声或外界干扰导致的孤立点或异常点。
  2. 预处理:为点云的后续处理(如重建或配准)提供干净的输入点云数据。
  3. 数据清理:在稠密点云中消除孤立的稀疏点。

二、代码实现

2.1关键函数

2.1.1 统计滤波实现

通过设置邻域搜索的邻居数量和标准偏差阈值,应用统计滤波。

#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>

// 统计滤波函数
pcl::PointCloud<pcl::PointXYZ>::Ptr statisticalOutlierRemoval(
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,  // 输入点云
    int mean_k,                                 // 邻居数量
    double std_dev_mul_thresh                   // 标准偏差阈值
)
{
    // 创建统计滤波对象,并设置参数
    pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
    sor.setInputCloud(cloud);                   // 设置输入点云
    sor.setMeanK(mean_k);                       // 设置每个点的邻域中邻居点的数量
    sor.setStddevMulThresh(std_dev_mul_thresh); // 设置标准偏差乘数阈值
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointXYZ>);
    sor.filter(*filtered_cloud);  // 应用滤波

    return filtered_cloud;  // 返回过滤后的点云
}

2.1.2 可视化函数

使用 PCL 可视化库展示原始点云和统计滤波后的点云。

#include <pcl/visualization/pcl_visualizer.h>

// 可视化原始点云和过滤后的点云
void visualizePointClouds(
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,          // 原始点云
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud  // 过滤后的点云
)
{
    // 创建可视化器
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Statistical Outlier Removal Viewer"));

    // 创建视口1,显示原始点云
    int vp_1;
    viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1);          // 创建左侧窗口
    viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_1);           // 设置白色背景
    viewer->addText("Raw Point Clouds", 10, 10, "v1_text", vp_1);  // 添加标题

    // 设置原始点云的颜色为红色
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color_handler(cloud, 255, 0, 0);  // 红色
    viewer->addPointCloud<pcl::PointXYZ>(cloud, cloud_color_handler, "original_cloud", vp_1);  // 添加原始点云

    // 创建视口2,显示过滤后的点云
    int vp_2;
    viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2);          // 创建右侧窗口
    viewer->setBackgroundColor(0.98, 0.98, 0.98, vp_2);        // 设置浅灰色背景
    viewer->addText("Filtered Point Clouds", 10, 10, "v2_text", vp_2);  // 添加标题

    // 设置过滤后的点云的颜色为绿色
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> filtered_cloud_color_handler(filtered_cloud, 0, 255, 0);  // 绿色
    viewer->addPointCloud<pcl::PointXYZ>(filtered_cloud, filtered_cloud_color_handler, "filtered_cloud", vp_2);  // 添加过滤后的点云

    // 设置点的大小(可选)
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "original_cloud", vp_1);
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "filtered_cloud", vp_2);

    // 启动可视化循环
    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);  // 刷新可视化器
    }
}

2.2完整代码

// C++头文件
#include <iostream>
// PCL头文件
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>  // 统计滤波
#include <pcl/visualization/pcl_visualizer.h>

// 统计滤波函数
pcl::PointCloud<pcl::PointXYZ>::Ptr statisticalOutlierRemoval(
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,  // 输入点云
    int mean_k,                                 // 邻居数量
    double std_dev_mul_thresh                   // 标准偏差阈值
)
{
    // 创建统计滤波对象,并设置参数
    pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
    sor.setInputCloud(cloud);                   // 设置输入点云
    sor.setMeanK(mean_k);                       // 设置每个点的邻域中邻居点的数量
    sor.setStddevMulThresh(std_dev_mul_thresh); // 设置标准偏差乘数阈值
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointXYZ>);
    sor.filter(*filtered_cloud);  // 应用滤波

    return filtered_cloud;  // 返回过滤后的点云
}

// 可视化原始点云和过滤后的点云
void visualizePointClouds(
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,          // 原始点云
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud  // 过滤后的点云
)
{
    // 创建可视化器
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Statistical Outlier Removal Viewer"));

    // 创建视口1,显示原始点云
    int vp_1;
    viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1);          // 创建左侧窗口
    viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_1);           // 设置白色背景
    viewer->addText("Raw Point Clouds", 10, 10, "v1_text", vp_1);  // 添加标题

    // 设置原始点云的颜色为红色
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color_handler(cloud, 255, 0, 0);  // 红色
    viewer->addPointCloud<pcl::PointXYZ>(cloud, cloud_color_handler, "original_cloud", vp_1);  // 添加原始点云

    // 创建视口2,显示过滤后的点云
    int vp_2;
    viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2);          // 创建右侧窗口
    viewer->setBackgroundColor(0.98, 0.98, 0.98, vp_2);        // 设置浅灰色背景
    viewer->addText("Filtered Point Clouds", 10, 10, "v2_text", vp_2);  // 添加标题

    // 设置过滤后的点云的颜色为绿色
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> filtered_cloud_color_handler(filtered_cloud, 0, 255, 0);  // 绿色
    viewer->addPointCloud<pcl::PointXYZ>(filtered_cloud, filtered_cloud_color_handler, "filtered_cloud", vp_2);  // 添加过滤后的点云

    // 设置点的大小(可选)
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "original_cloud", vp_1);
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "filtered_cloud", vp_2);

    // 启动可视化循环
    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);  // 刷新可视化器
    }
}

int main(int argc, char** argv)
{
    // ------------------------------读取点云数据---------------------------------
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    if (pcl::io::loadPCDFile("ro_bunny.pcd", *cloud) < 0)
    {
        PCL_ERROR("Could not read file\n");
        return (-1);  // 返回错误
    }

    // -------------------------------统计滤波---------------------------------
    int mean_k = 50;               // 设置邻居数量
    double std_dev_mul_thresh =1.0;  // 设置标准偏差乘数阈值
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud = statisticalOutlierRemoval(cloud, mean_k, std_dev_mul_thresh);  // 应用统计滤波

    // ------------------------------可视化原始点云和过滤后的点云---------------------------------
    visualizePointClouds(cloud, filtered_cloud);  // 调用可视化函数

    return 0;
}

三、实现效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2187367.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android SystemUI组件(10)禁用/重启锁屏流程分析

该系列文章总纲链接&#xff1a;专题分纲目录 Android SystemUI组件 本章关键点总结 & 说明&#xff1a; 说明&#xff1a;本章节持续迭代之前章节的思维导图&#xff0c;主要关注左侧上方锁屏分析部分 应用入口处理流程解读 即可。 在 Android 系统中&#xff0c;禁用锁屏…

C++初学者指南-5.标准库(第二部分)–随机数生成

C初学者指南-5.标准库(第二部分)–随机数生成 文章目录 C初学者指南-5.标准库(第二部分)–随机数生成基本概念例子统一随机数布尔值&#xff08;“抛硬币”&#xff09;正态分布具有独立概率的整数 怎么做种子引擎使用自定义生成器 shuffle算法分布类型概述通用接口均匀分布采样…

虚拟机 VMware 安装 macOS

macOS 界面 MAC OS IOS下载&#xff1a; amacOS Monterey by Techrechard.comwmacOS Monterey by Techrechard.com 下载&#xff1a;Unlocker-v2.0.1-x64 Mac OS X 虚拟机中更改屏幕分辨率 终端输入命令&#xff1a; sudo defaults write /Library/Preferences/com.apple.w…

C++11bind、function、lambda详细讲解

一.lambda表达式 关于lambda表达式&#xff0c;我之前是详细讲过的&#xff0c;现在我们只来做重点讲解&#xff08;如果存在疑问可以回看我之前的作品&#xff09;。 固定格式&#xff1a; []()->返回值{};([capture-list] (parameters) mutable -> return-type { state…

UE行为树编辑器图文笔记

对UE的编辑器实现有点好奇&#xff0c;于是从比较熟悉的行为树编辑器着手分析。以下为阅读UE源码后的个人理解&#xff0c;如有错误请指正。 编辑器基础 扩展编辑器的几种方式 MenuBar 菜单栏ToolBar 工具栏DetailCustomization 自定义细节面板&#xff0c;支持两种方式&…

西安做网站如何打造出色的企业网站

西安做网站如何打造出色的企业网站 随着数字化时代的到来&#xff0c;企业网站已成为展示企业形象、传播品牌价值的重要平台。在西安&#xff0c;如何打造出色的企业网站呢&#xff1f;以下几点建议可以帮助企业在激烈的竞争中脱颖而出。 **1. 清晰的网站定位** 首先&#xff…

【Godot4.3】匀速和匀变速直线运动粒子

概述 本篇论述&#xff0c;如何用加速度在Godot中控制粒子运动。 匀速和匀变速直线运动的统一 以下是匀变速运动的速度和位移公式&#xff1a; v t v 0 a t x t v 0 t 1 2 a t 2 v_tv_0 at \\ x_tv_0t \frac{1}{2}at^2 vt​v0​atxt​v0​t21​at2 当a 0 时&#xf…

计算机科学英语词汇汇总(下)Computer Science English Complete Vocabulary )

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…

0基础学习QT——配置开发环境

大纲 安装Qt配置Visual Studio 2022安装插件配置 测试 Qt框架&#xff0c;以其跨平台、高性能以及丰富的UI组件库而著称&#xff0c;是开发图形用户界面应用程序的理想选择。Visual Studio 2022提供了对Qt项目的深度支持&#xff0c;包括智能代码提示、代码导航、调试工具等&am…

(14)MATLAB莱斯(Rician)衰落信道仿真4

文章目录 前言一、改写莱斯分布概率密度函数的理论值二、仿真代码三、仿真结果总结 前言 本文通过将接收信号总功率设置为1&#xff0c;重写了莱斯衰落信道上接收信号幅度的理论PDF式。然后用MATLAB代码生成了在具有不同莱斯因子K的Ricean平坦衰落信道下接收到的信号样本&…

容器适配器-stack、queue、priority_queue和仿函数

目录 1.什么是适配器 2.deque 1.简单了解结构 2.deque的缺陷 3.为什么选择deque作为stack和queue的底层默认容器 3.stack&#xff08;栈&#xff09; 4.queue&#xff08;队列&#xff09; 5.仿函数 6.priority_queue&#xff08;优先级队列&#xff09;&#xff08;堆…

PlantUML中的实体关系图

概述 实体关系图&#xff08;Entity Relationship Diagrams&#xff0c;ERD&#xff09;是一种被广泛用于数据库建模的图。 1976年美籍华裔计算机科学家陈品山&#xff08;Peter Chen&#xff09;首次提出了Entity Relationship Modeling&#xff08;实体关系建模&#xff09…

数据结构-单链表的反转

一直在路上 目录 前言一、普通方法二、头插法三、递归法总结 前言 本篇文章介绍反转单链表的三种方法&#xff0c;分别为普通方法、头插法、递归法。 一、普通方法 普通方法是从第一个结点开始反转&#xff0c;然后反转剩余的结点。 普通方法需要保存当前结点的前驱和后继&a…

DevExpress WinForms v24.1新版亮点:富文本编辑器、电子表格组件功能升级

DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜…

自动驾驶-轨迹拼接

在进行自动驾驶的规划之前&#xff0c;要确定当前帧轨迹规划的起点&#xff0c;这个起点常被误认为是当前车辆的位置&#xff0c;即每次以车辆的当前位置进行轨迹规划&#xff1b;其实不是这样的&#xff0c;直观上&#xff0c;这会导致本次次规划的轨迹同上次规划的轨迹之间是…

如何计算服务需要部署多少台机器?

写在前面 遇到流量激增的性能问题&#xff0c;相信绝大多数人的第一反应不是优化代码而是加机器&#xff01;比如隔壁微博一旦出现爆炸性吃瓜&#xff0c;就会紧急扩机器&#xff0c;防止自己服务被打挂&#xff08;虽然经常被打挂 这篇文章我们就来讲一下如何 计算出一个服务…

项目配置说明

文章目录 一、下载 vscode 并安装相应扩展1.1 下载 vscode1.2 安装扩展 二、git 项目三、git 提交流程3.1 确定要提交的代码 四、git 拉新流程 一、下载 vscode 并安装相应扩展 1.1 下载 vscode vscode 我已经发群里了&#xff0c;或者自己去官网下载也行 1.2 安装扩展 打开…

四舵轮车辆中的舵轮角度计算

对于四舵轮车辆&#xff0c;或者对角线安装的双舵轮车辆来说&#xff0c;当同时存在线速度与角速度的时候&#xff0c;它的两个轮子的角度值是不一样的&#xff0c;而它的角度值与其当时的瞬心相关&#xff08;机器人模型与ICR(Instantaneous Center of Rotation)&#xff09;。…

IP6537_C_30W20V--移动设备快充的得力助手,集成 14 种快充协议的降压 SoC

IP6537_C_30W20V是一款集成同步开关的降压转换器、支 持 14 种输出快充协议、支持 Type-C 输出和 USB PD2.0/PD3.0(PPS)协议的 SoC&#xff0c;为车载充电器、 快充适配器、智能排插提供完整的解决方案。 IP6537_C_30W20V支持 USB Type-C 或者 USB A 输出&#xff0c; 5V 输出功…

火语言RPA流程组件介绍--模拟键盘输入

&#x1f6a9;【组件功能】&#xff1a;在浏览器网页中使用键盘操作模拟输入值 配置预览 配置说明 按键间隔(ms) 支持T或# 输入仅支持整型 两次输入按键的间隔,单位毫秒 输入内容 支持T或# 默认FLOW输入项 需要输入的内容 超时时间 支持T或# 输入仅支持整型 输入的超时时…