目录
一、概述
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;
}