注意:由八叉树进行的空间变化检测,可用在无序点云上。
某些由父类实现的可调用方法,如检查用户输入位置的体素块是否存在、获取树深、获取体素块中心点等在PCL八叉树的介绍:6.PCL八叉树关键函数中提及。
1.原理
对无序点云在空间变化上的检测,即对前后两幅点云在八又树结构下的空间节点差异检测。
(1)载入原始点云A,并生成第一个八叉树结构。
(2)切缓冲,载入原始点云B,生成第二个八叉树结构。
(3)比较两个八叉树结构,若某些叶子结点在第二个八叉树上,但是不在第一个八叉树上,那么就认为这些叶子节点内的点是空间上变化多出来的点。
如下图:
比较完整兔子、半截兔子两个点云的空间变化信息时,完整兔子八叉树结构如图1,半截兔子八叉树结构如图2。
二者八叉树结构重叠,比较二者八叉数节点的区别,若空间节点信息有差异,即为空间检测差异。
2.使用场景
工作中常用于:树木生长检测、建筑物重新施工检测等。
3.注意事项
无
4.代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/octree/octree_pointcloud_changedetector.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
int main()
{
/***************八叉树空间信息检测********************/
// 原始点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud0(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile("D:/code/csdn/data/bunny0.pcd", *cloud0); // 原始点云数据0
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile("D:/code/csdn/data/bunny.pcd", *cloud1); // 原始点云数据1
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_change(new pcl::PointCloud<pcl::PointXYZ>); // 变化点云
// 构建八叉树
pcl::octree::OctreePointCloudChangeDetector<pcl::PointXYZ>octree(0.01);
octree.setInputCloud(cloud0); // 添加cloud0点云到八叉树
octree.addPointsFromInputCloud(); // 构建cloud0八叉树
octree.switchBuffers(); // 交换八叉树缓存,此时cloud0对应的八叉树仍在内存中
octree.setInputCloud(cloud1); // 添加cloud1点云到八叉树
octree.addPointsFromInputCloud(); // 构建cloud1八叉树
std::vector<int>newPointIdxVector; // 保存cloud0对应的八叉树在cloud1对应八叉树中没有的点索引
octree.getPointIndicesFromNewVoxels(newPointIdxVector);
pcl::copyPointCloud(*cloud1, newPointIdxVector, *cloud_change); // 复制结果到新点云
// 展示
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewR(new pcl::visualization::PCLVisualizer("raw"));
viewR->addPointCloud<pcl::PointXYZ>(cloud0, "raw cloud");
viewR->addPointCloud<pcl::PointXYZ>(cloud1, "raw cloud");
viewR->addPointCloud<pcl::PointXYZ>(cloud_change, pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>(cloud_change, 0, 0, 255), "r cloud");
viewR->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "raw cloud");
while (!viewR->wasStopped())
{
viewR->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
}
5.结果展示
打印信息:
可视化结果: