目录
一、概述
1.1原理
1.2实现步骤
1.3应用场景
二、代码实现
2.1关键函数
2.1.1八叉树构建与变化检测
2.1.2检测变化的点云
2.2完整代码
三、实现效果
PCL点云算法汇总及实战案例汇总的目录地址链接:
PCL点云算法与项目实战案例汇总(长期更新)
一、概述
空间变化检测是点云处理中常见的任务之一,常用于监测不同时间点的点云数据集之间的变化。PCL 中可以通过 八叉树 来高效完成点云的空间变化检测。通过构建两组点云的八叉树,比较相同空间位置上的体素变化,快速检测出两组点云之间的空间变化。
1.1原理
空间变化检测的核心思想是:将两组点云(例如不同时刻采集的数据)通过八叉树进行空间划分。每个八叉树节点(体素)代表空间中的一个区域。通过比较两个点云的八叉树节点,可以快速检测哪些体素中的点数或位置发生了变化,进而得出空间变化区域。
1.2实现步骤
- 读取两组点云数据。
- 使用 pcl::octree::OctreePointCloudChangeDetector 分别对两组点云进行八叉树构建。
- 比较两组点云的八叉树结构,检测变化的体素。
- 可视化检测结果,突出显示发生变化的区域。
1.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;
}