PCL 用八叉树完成空间变化检测

news2024/10/1 21:35:43

目录

一、概述

1.1原理

1.2实现步骤

1.3应用场景

二、代码实现

2.1关键函数

2.1.1八叉树构建与变化检测

2.1.2检测变化的点云

2.2完整代码

三、实现效果


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

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


一、概述

        空间变化检测是点云处理中常见的任务之一,常用于监测不同时间点的点云数据集之间的变化。PCL 中可以通过 八叉树 来高效完成点云的空间变化检测。通过构建两组点云的八叉树,比较相同空间位置上的体素变化,快速检测出两组点云之间的空间变化。

1.1原理

        空间变化检测的核心思想是:将两组点云(例如不同时刻采集的数据)通过八叉树进行空间划分。每个八叉树节点(体素)代表空间中的一个区域。通过比较两个点云的八叉树节点,可以快速检测哪些体素中的点数或位置发生了变化,进而得出空间变化区域。

1.2实现步骤

  1. 读取两组点云数据。
  2. 使用 pcl::octree::OctreePointCloudChangeDetector 分别对两组点云进行八叉树构建。
  3. 比较两组点云的八叉树结构,检测变化的体素。
  4. 可视化检测结果,突出显示发生变化的区域。

1.3应用场景

  1. 监控变化:用于监测环境中物体的移动或消失。
  2. 场景重建:比较不同时间段的场景点云,检测物体位置变化。
  3. 质量检测:对比不同状态下的物体点云数据,发现差异。

二、代码实现

2.1关键函数

2.1.1八叉树构建与变化检测

        PCL 提供的 pcl::octree::OctreePointCloudChangeDetector 可以同时构建八叉树并完成空间变化检测。

#include <pcl/octree/octree_pointcloud_changedetector.h>

// 设置八叉树分辨率
float resolution = 0.05f;
pcl::octree::OctreePointCloudChangeDetector<pcl::PointXYZ> octree(resolution);

// 构建八叉树并添加第一组点云数据
octree.setInputCloud(cloud1);  // cloud1 是第一组点云
octree.addPointsFromInputCloud();  // 添加第一组点云到八叉树

// 切换到第二组点云,重新构建八叉树并检测变化
octree.switchBuffers();  // 切换八叉树缓存,准备添加第二组点云
octree.setInputCloud(cloud2);  // cloud2 是第二组点云
octree.addPointsFromInputCloud();  // 添加第二组点云

2.1.2检测变化的点云

        使用 getPointIndicesFromNewVoxels 获取在两个点云之间发生变化的体素。

std::vector<int> newPointIdxVector;
octree.getPointIndicesFromNewVoxels(newPointIdxVector);  // 获取新体素中的点索引

2.2完整代码

#include <iostream>
#include <vector>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/octree/octree_pointcloud_changedetector.h>
#include <pcl/visualization/pcl_visualizer.h>

int main(int argc, char** argv)
{
    // -----------------------------读取两组点云数据---------------------------------
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud2(new pcl::PointCloud<pcl::PointXYZ>);

    if (pcl::io::loadPCDFile<pcl::PointXYZ>("cloud1.pcd", *cloud1) == -1 || 
        pcl::io::loadPCDFile<pcl::PointXYZ>("cloud2.pcd", *cloud2) == -1)
    {
        PCL_ERROR("Couldn't read the PCD files!\n");
        return -1;
    }

    // -----------------------------构建八叉树并检测变化---------------------------------
    float resolution = 0.05f;  // 八叉树的分辨率
    pcl::octree::OctreePointCloudChangeDetector<pcl::PointXYZ> octree(resolution);

    // 添加第一组点云到八叉树
    octree.setInputCloud(cloud1);
    octree.addPointsFromInputCloud();

    // 切换到第二组点云并检测变化
    octree.switchBuffers();  // 切换缓存
    octree.setInputCloud(cloud2);
    octree.addPointsFromInputCloud();  // 添加第二组点云

    // 获取变化的点索引
    std::vector<int> newPointIdxVector;
    octree.getPointIndicesFromNewVoxels(newPointIdxVector);

    // -----------------------------可视化变化结果---------------------------------
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Change Detection Viewer"));

    // 设置背景颜色为白色
    viewer->setBackgroundColor(1.0, 1.0, 1.0);  // 白色背景

    // 显示第一组点云(绿色)
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud1_color_handler(cloud1, 0, 255, 0);
    viewer->addPointCloud(cloud1, cloud1_color_handler, "cloud1");

    // 显示变化的点(红色)
    pcl::PointCloud<pcl::PointXYZ>::Ptr changed_points(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::copyPointCloud(*cloud2, newPointIdxVector, *changed_points);  // 将变化的点复制出来
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> changed_points_color_handler(changed_points, 255, 0, 0);
    viewer->addPointCloud(changed_points, changed_points_color_handler, "changed_points");

    // 设置点的大小
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud1");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 4, "changed_points");

    // 添加坐标系
    viewer->addCoordinateSystem(1.0);
    viewer->initCameraParameters();

    // 可视化循环
    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);
    }

    return 0;
}

三、实现效果

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

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

相关文章

快速排序(C语言实现)

目录 基本概念 Hoare版本 动图演示 思路 代码实现&#xff1a; 性能分析 取Key优化 三数取中法选择基准&#xff08;Median-of-Three Partitioning&#xff09; 实现步骤 代码实现 挖坑法 基本步骤 动图 示例说明 代码实现 前后指针法 动图示范 思路 代码实…

Linux操作系统中docker

1、docker概述 1、什么是docker Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Linux或Windows&#xff08;对于windows不是太友好&#xff09;操作系统的机器上&#xff0c;也可以…

Amazon EC2:权限设置指南,构建安全的云环境

在数字化转型的浪潮中&#xff0c;企业纷纷将业务迁移到云端&#xff0c;以提高灵活性和效率。Amazon Elastic Compute Cloud&#xff08;EC2&#xff09;作为 AWS 的核心服务之一&#xff0c;为企业提供了一个强大的云计算平台。然而&#xff0c;随着云环境的复杂性增加&#…

DHCP 中继器

在实际应用中可能会遇到一个比较大的物理网络中存在多个ip子网&#xff0c;而每个ip子网的主机都需要DHCP服务器来动态分配ip地址&#xff0c;实现的方法有两种: 第一种是在每一个子网中设置DHCP服务器&#xff0c;将其分别为每个子网分配ip地址&#xff0c;但此方法会增加开销…

【Hadoop】【vim编辑器】【~/.bashrc 文件】如何编辑

1. 进入 vim 编辑器 在终端中输入以下命令&#xff1a; vim ~/.bashrc 2. 进入插入模式 打开文件后&#xff0c;你将处于普通模式。在普通模式下&#xff0c;你不能直接编辑文本。 要进入插入模式&#xff0c;请按下 i 键。这时&#xff0c;你应该会看到屏幕底部出现 -- 插…

优化java中 HashMap 的容量](capacity值)

我们很多人都知道&#xff0c;分配比我们所需更多的内存可能会对应用程序的性能产生负面影响。因此&#xff0c;使用带有容量的构造函数创建列表可能会产生很大的不同。 但是&#xff0c;使用Maps时&#xff0c;这个优化步骤可能不是那么简单。在本文中&#xff0c;我们将学习…

鸿蒙OpenHarmony【小型系统基础内核(互斥锁)】子系统开发

互斥锁 基本概念 互斥锁又称互斥型信号量&#xff0c;用于实现对共享资源的独占式处理。当有任务持有时&#xff0c;这个任务获得该互斥锁的所有权。当该任务释放它时&#xff0c;任务失去该互斥锁的所有权。当一个任务持有互斥锁时&#xff0c;其他任务将不能再持有该互斥锁…

Redis 主从复制的实现过程

Redis 主从复制的实现过程 1. 初始同步请求2. 快照生成与发送3. 从服务器载入数据4. 增量同步5. 持续同步与部分重同步 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; Redis 的主从复制是一个高效的数据同步机制&#xff0c;主要步骤为以下…

5分钟内不能重复发送验证码!

文章目录 引言校验5分钟内不能重复发送验证码生成验证内容保存验证码到缓存获取缓存验证内容验证短信验证码是否正确数据模型see also引言 防止被恶意攻击,使用需要限制用户获取验证码的频率,例如5分钟内不能重复发送验证码!获取验证码接口,也必须进行签名校验。 使用Red…

单片机STM32 外部中断线的使用笔记

一、STM32外部中断线问题小结 1.1 不同的端口同一PIN 在STM32中&#xff0c;不同的端口&#xff08;如PA、PB、PC等&#xff09;上的相同PIN号&#xff08;如PA1、PB1、PC1&#xff09;可以共用一个外部中断线&#xff08;EXTI_Line&#xff09;。这意味着&#xff0c;虽然这些…

[系列]相关的知识点关联

系列 独立&不相关不相关&正交协方差&互相关相关系数协方差&相关系数余弦系数&内积余弦系数&相关系数滤波&卷积卷积&互相关互相关&内积互相关&归一化互相关

Jenkins入门:从搭建到部署第一个Springboot项目(踩坑记录)

本文讲述在虚拟机环境下(模拟服务器)&#xff0c;使用docker方式搭建jenkins&#xff0c;并部署一个简单的Springboot项目。仅记录关键步骤和遇到的坑&#xff0c;后续再进行细节补充。 一、环境准备和基础工具安装 1. 环境 系统环境为本机vmware创建的Ubuntu24.04。 2. yum…

Unity 3D UGUI 系统一口气讲完!(^U^)ノ~YO

UGUI Canvas 画布 Canvas画布是摆放所有 UI 元素的区域&#xff0c;在场景中创建的所有控件都会自动变为 Canvas游戏对象的子对象。 若场景中没有画布&#xff0c;在创建控件时会自动创建画布。 不论是你主动创建还是被动创建&#xff0c;系统都会自动创建一个名为 EventSys…

使用Python解决数据分析中的相关性分析

目录 1.相关系数基础1.1 使用Pandas计算皮尔逊相关系数1.2 计算物品A与其他物品的相关系数1.3 用户间的相关系数1.4 获取相关系数矩阵 2. 相似度计算的Python实现2.1 欧式距离2.2 余弦相似度2.3 皮尔逊相关系数的手动实现 3. 总结 在数据分析中&#xff0c;相关系数是衡量两个变…

应用案例 | HK-MSR数据记录仪如何计算滑雪时膝盖上的应力?

计算滑雪时膝盖上的应力 阿尔卑斯山高山滑雪运动员在滑雪时对膝盖产生的压力有多大&#xff1f;Thea Waldleben&#xff0c;现任瑞士青年速降赛冠军&#xff0c;在她的 "Maturaarbeit"&#xff08;考试项目&#xff09;中回答了这个问题。通过使用HK-MSR数据记录仪&…

Python OpenCV精讲系列 - 边缘检测深入理解(十三)

&#x1f496;&#x1f496;⚡️⚡️专栏&#xff1a;Python OpenCV精讲⚡️⚡️&#x1f496;&#x1f496; 本专栏聚焦于Python结合OpenCV库进行计算机视觉开发的专业教程。通过系统化的课程设计&#xff0c;从基础概念入手&#xff0c;逐步深入到图像处理、特征检测、物体识…

地质工程专业职称申报条件详细解读

一、初级&#xff08;助理&#xff09;地质工程工程师评审条件&#xff1a; 1、理工类或者地质工程类专业毕业 2、专科毕业满3年或本科毕业满1年 3、研究生毕业&#xff0c;从事本专业技术工作&#xff0c;当年内考核认定 二、中级地质工程工程师评审条件&#xff1a; 1、理工…

解决远程连接AlpineLinux Mysql/MariaDB 无法连接的问题

&#x1f525;博客介绍&#xff1a; EvLast &#x1f3a5;系列专栏&#xff1a; << C项目>> <<数据结构与算法>> << 算法入门>> &#x1f3a5; 当前专栏:<< C项目>> 专题 : 解决开发中的日常Bug &#x1f44d;&#x1f44…

服务端的 Session 详解

0x01&#xff1a;Session 简介 Session 是在 Cookie 的基础上发展的&#xff0c;其主要功能和 Cookie 一样&#xff0c;都是为了解决 HTTP 无状态的痛点&#xff0c;和 Cookie 不同的是&#xff0c;它是将大部分数据存储在了服务端&#xff0c;而只给用户一个 SESSID&#xff…

django学习入门系列之第十点《A 案例: 员工管理系统21》

文章目录 16 Ajax(订单案例)16.9 编辑想要去数据库中获取数据时:对象/字典将具体内容的错误信息传入到前端&#xff08;Ajax&#xff09;将数据库数据传入前端&#xff08;Ajax&#xff09;清空新建订单的数据 16.10 编辑后保存 往期回顾 16 Ajax(订单案例) 16.9 编辑 点击编辑…