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

目录

一、概述

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;
}

三、实现效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值