PCL 点云模型滤波(圆形)

news2024/11/23 15:51:37

目录

一、概述

1.1原理

1.2实现步骤

1.3应用场景

二、代码实现

2.1关键函数

2.1.1 生成点云数据

2.1.2 模型滤波函数

2.1.3 可视化函数

2.2完整代码

三、实现效果


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

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


一、概述

        模型点云滤波 是通过基于特定几何形状的模型(例如球体、平面等)来识别点云中符合该模型的点,并将它们从点云中提取出来或者移除。这种滤波技术广泛应用于点云数据的分割、去噪和特征提取等任务。

1.1原理

        通过预设几何模型(如球体、平面等),在点云数据中搜索与该模型拟合度高的点,并将其从点云中提取出来或过滤掉。具体的滤波过程依赖于模型系数以及距离阈值,以确保提取的点符合指定的几何特征。

1.2实现步骤

  1. 生成包含噪声和球体的模拟点云数据。
  2. 定义球体模型,并设定模型参数(如球心和半径)。
  3. 使用 pcl::ModelOutlierRemoval 对点云数据进行模型滤波,提取符合球体模型的点云。
  4. 可视化原始点云与滤波后的点云对比。

1.3应用场景

  1. 几何特征提取:从点云数据中提取特定几何形状(如平面、球体等)。
  2. 去除噪声点:移除不符合模型的噪声点。
  3. 点云分割:将点云划分为符合模型的点和不符合模型的点。

二、代码实现

2.1关键函数

2.1.1 生成点云数据

生成包含噪声点和球体点的模拟点云数据

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

// 生成噪声点和球体点的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr generatePointCloud(int noise_size, int sphere_size)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    cloud->width = noise_size + sphere_size;
    cloud->height = 1;
    cloud->points.resize(cloud->width * cloud->height);

    // 生成噪声点
    for (size_t i = 0; i < noise_size; ++i)
    {
        cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
    }

    // 生成球体点
    double rand_x1 = 1, rand_x2 = 1;
    for (size_t i = noise_size; i < noise_size + sphere_size; ++i)
    {
        while (pow(rand_x1, 2) + pow(rand_x2, 2) >= 1)
        {
            rand_x1 = (rand() % 100) / (50.0f) - 1;
            rand_x2 = (rand() % 100) / (50.0f) - 1;
        }
        double pre_calc = sqrt(1 - pow(rand_x1, 2) - pow(rand_x2, 2));
        cloud->points[i].x = 2 * rand_x1 * pre_calc;
        cloud->points[i].y = 2 * rand_x2 * pre_calc;
        cloud->points[i].z = 1 - 2 * (pow(rand_x1, 2) + pow(rand_x2, 2));
        rand_x1 = 1;
        rand_x2 = 1;
    }

    return cloud;
}

2.1.2 模型滤波函数

根据定义的球体模型,对点云数据进行模型滤波,提取符合球体模型的点。

#include <pcl/filters/model_outlier_removal.h>
#include <pcl/model_coefficients.h>

// 对点云进行模型滤波,提取符合球体模型的点
pcl::PointCloud<pcl::PointXYZ>::Ptr applyModelFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
    pcl::ModelCoefficients sphere_coeff;
    sphere_coeff.values.resize(4); // 定义球体模型参数
    sphere_coeff.values[0] = 0;    // 球心的 x 坐标
    sphere_coeff.values[1] = 0;    // 球心的 y 坐标
    sphere_coeff.values[2] = 0;    // 球心的 z 坐标
    sphere_coeff.values[3] = 1;    // 球体的半径

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);

    pcl::ModelOutlierRemoval<pcl::PointXYZ> filter;
    filter.setModelCoefficients(sphere_coeff);   // 设置球体模型参数
    filter.setThreshold(0.05);                   // 设置距离阈值
    filter.setModelType(pcl::SACMODEL_SPHERE);   // 设置模型类型为球体
    filter.setInputCloud(cloud);
    filter.filter(*cloud_filtered);              // 滤波操作

    return cloud_filtered;
}

2.1.3 可视化函数

#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("Model Filter Viewer"));

    int vp_1, vp_2;
    viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1);   // 创建左侧窗口
    viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_1);    // 设置白色背景
    viewer->addText("Original PointCloud", 10, 10, "vp1_text", vp_1);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color(cloud, 255, 0, 0); // 原始点云红色
    viewer->addPointCloud(cloud, cloud_color, "original_cloud", vp_1);

    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 PointCloud", 10, 10, "vp2_text", vp_2);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> filtered_color(filtered_cloud, 0, 255, 0); // 滤波点云绿色
    viewer->addPointCloud(filtered_cloud, filtered_color, "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完整代码

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/model_outlier_removal.h>
#include <pcl/visualization/pcl_visualizer.h>

// 生成包含噪声和球体点的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr generatePointCloud(int noise_size, int sphere_size)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    cloud->width = noise_size + sphere_size;
    cloud->height = 1;
    cloud->points.resize(cloud->width * cloud->height);

    // 生成噪声点
    for (size_t i = 0; i < noise_size; ++i)
    {
        cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
    }

    // 生成球体点
    double rand_x1 = 1, rand_x2 = 1;
    for (size_t i = noise_size; i < noise_size + sphere_size; ++i)
    {
        while (pow(rand_x1, 2) + pow(rand_x2, 2) >= 1)
        {
            rand_x1 = (rand() % 100) / (50.0f) - 1;
            rand_x2 = (rand() % 100) / (50.0f) - 1;
        }
        double pre_calc = sqrt(1 - pow(rand_x1, 2) - pow(rand_x2, 2));
        cloud->points[i].x = 2 * rand_x1 * pre_calc;
        cloud->points[i].y = 2 * rand_x2 * pre_calc;
        cloud->points[i].z = 1 - 2 * (pow(rand_x1, 2) + pow(rand_x2, 2));
        rand_x1 = 1;
        rand_x2 = 1;
    }

    return cloud;
}

// 对点云进行模型滤波,提取符合球体模型的点
pcl::PointCloud<pcl::PointXYZ>::Ptr applyModelFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
    pcl::ModelCoefficients sphere_coeff;
    sphere_coeff.values.resize(4);
    sphere_coeff.values[0] = 0;
    sphere_coeff.values[1] = 0;
    sphere_coeff.values[2] = 0;
    sphere_coeff.values[3] = 1;

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);

    pcl::ModelOutlierRemoval<pcl::PointXYZ> filter;
    filter.setModelCoefficients(sphere_coeff);
    filter.setThreshold(0.05);
    filter.setModelType(pcl::SACMODEL_SPHERE);
    filter.setInputCloud(cloud);
    filter.filter(*cloud_filtered);

    return cloud_filtered;
}

// 可视化原始点云和滤波后的点云
void visualizePointClouds(
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud
)
{
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Model Filter Viewer"));

    int vp_1, vp_2;
    viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1);
    viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_1);
    viewer->addText("Original PointCloud", 10, 10, "vp1_text", vp_1);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color(cloud, 255, 0, 0);
    viewer->addPointCloud(cloud, cloud_color, "original_cloud", vp_1);

    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 PointCloud", 10, 10, "vp2_text", vp_2);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> filtered_color(filtered_cloud, 0, 255, 0);
    viewer->addPointCloud(filtered_cloud, filtered_color, "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()
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = generatePointCloud(500, 10000);  // 生成点云数据

    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud = applyModelFilter(cloud); // 应用模型滤波

    visualizePointClouds(cloud, filtered_cloud);  // 可视化原始点云和滤波后的点云

    return 0;
}

三、实现效果

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

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

相关文章

「JavaScript深入」彻底理解JS中的闭包

JavaScript深入 — 闭包 一、概念二、示例三、实用的闭包四、用闭包模拟私有方法五、一个常见错误&#xff1a;在循环中创建闭包&#x1f330; 另一个经典例子-定时器与闭包 六、优劣好处坏处解决 七、图解闭包八、应用 &#x1f4aa;封装私有变量函数工厂异步操作中的回调函数…

css中背景色、背景图的使用

1、同时使用背景色、背景图片 参考链接&#xff1a;链接 以下样式&#xff0c;背景色在图片下方(缺点&#xff1a;图片不透明时&#xff0c;背景色会被完全遮挡。) .header {height: 100%;width: 100%;background-color: #000;background-image: url(/static/images/back.pn…

云原生之运维监控实践-使用Prometheus与Grafana实现对MySQL和Redis服务的监测

背景 如果你要为应用程序构建规范或用户故事&#xff0c;那么务必先把应用程序每个组件的监控指标考虑进来&#xff0c;千万不要等到项目结束或部署之前再做这件事情。——《Prometheus监控实战》 去年写了一篇在Docker环境下部署若依微服务ruoyi-cloud项目的文章&#xff0c;当…

数据结构之手搓顺序表(顺序表的增删查改)

目录 文章目录 前言 一、什么是顺序表&#xff1f; 二、动态顺序表的实现 1.头文件定义 2.实现顺序表的初始化 3.检查顺序表空间容量是否足够&#xff0c;不够就增容 4.顺序表的销毁 5.顺序表的打印 6.顺序表的尾插 7.顺序表的头插 8.顺序表的头删 9.顺序表的尾删 10.顺序…

LeetCode题练习与总结:二叉树的所有路径--257

一、题目描述 给你一个二叉树的根节点 root &#xff0c;按 任意顺序 &#xff0c;返回所有从根节点到叶子节点的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,null,5] 输出&#xff1a;["1->2->5","1->…

RabbitMQ基本原理

一、基本结构 所有中间件技术都是基于 TCP/IP 协议基础之上进行构建新的协议规范&#xff0c;RabbitMQ遵循的是AMQP协议&#xff08;Advanced Message Queuing Protocol - 高级消息队列协议&#xff09;。 生产者发送消息流程&#xff1a; 1、生产者和Broker建立TCP连接&#…

国庆同欢,祖国昌盛!肌肉纤维启发,水凝胶如何重构聚合物

在这个国庆佳节&#xff0c;我们共同感受祖国的繁荣昌盛&#xff0c;同时也迎来了知识的探索之旅。今天来了解聚合物架构的重构的研究——《Hydrogel‐Reactive‐Microenvironment Powering Reconfiguration of Polymer Architectures》发表于《Advanced Science》。材料科学不…

【数据结构与算法】算法和算法分析

文章目录 一.算法1.定义2.描述 二.算法与程序三.算法特性四.算法效率的度量4.1算法时间事前分析法算法时间复杂度的渐进表示法分析算法时间复杂度的基本方法 4.2算法空间 数据的逻辑结构映像到内存就是数据的存储结构&#xff0c;针对数据的逻辑结构可以选择多种存储结构。数据…

Kotlin:2.0.0 的新特性

一、概述 kotlin 2.0.0版本英文官方文档 The Kotlin 2.0.0 release is out and the new Kotlin K2 compiler is Stable! Additionally, here are some other highlights: Kotlin 2.0.0发布了&#xff0c;新的Kotlin K2编译器已经稳定了。此外&#xff0c;以下是其他一些亮点: …

Linux操作系统中dubbo

1、简介 dubbo框架是做微服务通信的&#xff0c;是由阿里巴巴开发&#xff0c;后捐赠给阿帕奇基金会。 2、与OpenFeign的区别 dubbo是采用RPC协议实现微服务通信&#xff0c;OpenFeign是采用Http请求的方式实现的。 OpenFeign 最简单的&#xff0c;就是Spring公司开发的&am…

TinyAP:使用TinyML对抗Wi-Fi攻击的智能接入点

论文标题&#xff1a; 英文&#xff1a;TinyAP: An intelligent Access Point to combat Wi-Fi attacks using TinyML中文&#xff1a;TinyAP&#xff1a;使用TinyML对抗Wi-Fi攻击的智能接入点 作者信息&#xff1a; Anand Agrawal 和 Rajib Ranjan Maiti&#xff0c;来自印…

C语言常用标准库 -- 5.<time.h>

目录 引言 5. C标准库--time.h 5.1 简介 5.2 常量与宏 5.3 库变量 5.4 库宏 5.5 库函数 5.6 注意事项 &#x1f308;你好呀&#xff01;我是 程序猿 &#x1f30c; 2024感谢你的陪伴与支持 ~ &#x1f680; 欢迎一起踏上探险之旅&#xff0c;挖掘无限可能&#xff0c;…

线程池面试集

目录 线程池中提交一个任务的流程是怎样的? 线程池有五种状态 如何优雅的停止一个线程? 线程池的核心线程数、最大线程数该如何设置? 如何理解Java并发中的可见性、原子性、有序性? Java死锁如何避免? 线程池中提交一个任务的流程是怎样的? 线程池有五种状态 如何优…

【docker学习】Linux系统离线方式安装docker环境方法

centos7-linux安装docker(离线方式) 下载docker的安装文件 https://download.docker.com/linux/static/stable/x86_64/ 下载的是&#xff1a;docker-18.06.3-ce.tgz 这个压缩文件 将docker-18.06.3-ce.tgz文件上传到centos7-linux系统上&#xff0c;用ftp工具上传即可 解压…

《RabbitMQ篇》基本概念介绍

MQ功能 解耦 MQ允许不同系统或组件之间松散耦合。发送者和接收者不需要直接连接&#xff0c;从而提高了系统的灵活性和可维护性。异步处理 使用MQ可以实现异步消息传递&#xff0c;发送者可以将消息放入队列后立即返回&#xff0c;不必等待接收者处理。这提高了系统的响应速度…

鸿蒙NEXT开发-ArkTS(基于最新api12稳定版)

注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章写的好的话&#xff0c;可以点下关注&#xff0c;博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…

Spring IoC笔记

目录 1.什么是 IoC&#xff1f; 2.IoC类注解&#xff08;五大注解&#xff09; 2.1那为什么要这么多类注解&#xff1f; 2.2五大注解是不是可以混用&#xff1f; 2.3程序被spring管理的条件是&#xff1f; 3.bean对象 3.1Bean 命名约定 3.2获取bean对象 4.⽅法注解 B…

《应急通信产业发展研究报告》蓝皮书解读

近日&#xff0c;中国信通院发布了《应急通信产业发展研究报告》蓝皮书&#xff0c;该报告是对中国应急通信产业现状、发展趋势及其政策环境的综合分析&#xff0c;旨在为行业发展提供参考与指导。以下是小编对该蓝皮书的一些内容解读&#xff1a; 1.应急通信的重要性 应急通信…

2.点位管理|前后端如何交互——帝可得后台管理系统

目录 前言点位管理菜单模块1.需求说明2.库表设计3.生成基础代码0 .使用若依代码生成器最终目标1.创建点位管理2.添加数据字典3.配置代码生成信息4.下载代码并导入项目 4.优化菜单——点位管理1.优化区域管理2.增加点位数3. 合作商4.区域管理中添加查看详情功能5.合作商添加点位…

【拥抱AIGC】通义灵码扩展管理

通义灵码提供了扩展管理&#xff0c;支持自定义指令&#xff0c;满足企业编码场景的扩展诉求。 适用版本 企业标准版、企业专属版 通义灵码管理员、组织内全局管理员&#xff08;专属版&#xff09;在通义灵码控制台-扩展管理中&#xff0c;进行自定义指令的管理、查看自定义…