PCL 八叉树的介绍(octree_octreePointcloud)

PCL专栏目录及须知

PCL中,往往使用八叉树的子类,而不是直接使用 pcl::octree::OctreePointCloud这个基类。

子类在6.PCL八叉树关键函数中展示。

PCL中:将三维空间等分为8份,分配空间对象。并不停地迭代,直至最大分辨率。其中,八叉树的每个结点表示一个正方体的体积元素,每一个结点最多有八个子节点。

在cloudcompare中如何生成并可视化八叉树

1.构造原理

  1. 设定最大递归深度。
  2. 找出场景的最大尺寸,并以此尺寸建立第一个立方体。
  3. 依序将单位元素丢入能包含且没有子节点的立方体
  4. 若没达到最大递归深度,就进行细分八等份,再讲该立方体所装的单位元元素全部分组给八个子立方体
  5. 若发现子立方体所分配到的单位元元素数量不为零且跟父立方体一样,则该子立方体停止细分
  6. (因为根据空间分割理论,细分的空间所得到的分配必定较少,若是一样的数目,再怎么切,数目还是一样)
  7. 重复3,直到到达最大递归深度。

2.数据结构

八叉树这种树结构中,每个节点的子节点数量永远是8。假设原目标(点云)被一个大立方体包含,八叉树的作用就是细分该大立方体,每个结点对应一个立方体空间。其中八叉树的结点分为三类:

灰色结点:它对应的立方体部分被目标占据(非叶结点)

白色结点:它对应的立方体没有被目标占据(叶结点)

黑色结点:它对应的立方体完全被目标占据(叶结点)

对于非叶结点,数据结构以八元数法进行区分,分解为更小的子区块,每个区块有结点容量,当结点达到最大容量(八叉树最大递归深度)时结点停止分裂。

3.分割终止判定

若不对空间划分做一定的条件限制,则会对空间无限划分下去。常见的限制条件为:

(1)节点中的对象数量限制

(2)节点的最小尺寸

4.查询节点

从根节点开始,如果找到给定点的节点,递归搜索,然后返回true,如果遇到空节点或边界点或空点,然后返回false。

如果找到一个内部节点,返回该节点(即我们查询的结点)。

5.优缺点

优点:使用八叉树可以快速进行三维目标的集合运算,如交、并、补、差等,亦可快速进行最邻近区域或点的搜索。

缺点:存储空间消耗。

6.PCL八叉树关键函数

(1)PCL中所有pcl::octree::OctreePointCloud的子类均可调用以下方法。

常用子类为:

1)八叉树搜索类

pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree;

2)八叉树空间变化检测类

pcl::octree::OctreePointCloudChangeDetector<pcl::PointXYZ> octree;

3)八叉树点云压缩类

pcl::io::OctreePointCloudCompression<pcl::PointXYZRGB> compression;

(2)子类常调用的通用函数

 1)检查用户输入位置的体素块是否存在

bool
  isVoxelOccupiedAtPoint(const double point_x_arg,
                         const double point_y_arg,
                         const double point_z_arg) const;

2)获取树深

  inline uindex_t
  getTreeDepth() const
  {
    return this->octree_depth_;
  }

3)获取体素块中心点

  uindex_t
  getOccupiedVoxelCenters(AlignedPointTVector& voxel_center_list_arg) const;

4)获取与线段相交的体素中心的PointT向量

  uindex_t
  getApproxIntersectedVoxelCentersBySegment(const Eigen::Vector3f& origin,
                                            const Eigen::Vector3f& end,
                                            AlignedPointTVector& voxel_center_list,
                                            float precision = 0.2);

5)获取八叉树的点云边界

  void
  getBoundingBox(double& min_x_arg,
                 double& min_y_arg,
                 double& min_z_arg,
                 double& max_x_arg,
                 double& max_y_arg,
                 double& max_z_arg) const;

6)计算给定树深度处体素的平方直径

  double
  getVoxelSquaredDiameter(uindex_t tree_depth_arg) const;

7)生成八叉树当前迭代器的边界

  inline void
  getVoxelBounds(const OctreeIteratorBase<OctreeT>& iterator,
                 Eigen::Vector3f& min_pt,
                 Eigen::Vector3f& max_pt) const
  {
    this->genVoxelBoundsFromOctreeKey(iterator.getCurrentOctreeKey(),
                                      iterator.getCurrentOctreeDepth(),
                                      min_pt,
                                      max_pt);
  }

7.八叉树形态示例图

下图中每个可见的方格即为八叉树中拥有点云点的子节点。

### PCL 中基于八叉树的空间变化检测 PCL(Point Cloud Library)提供了 `OCTree_OctreePointCloudChangeDetector` 类来实现点云之间的空间变化检测。该功能的核心在于利用八叉树结构对点云数据进行分层划分,并通过比较不同时间戳下的点云分布情况,识别新增或移除的体素。 #### 构建 CMake 工程 为了使用 PCL八叉树模块,需配置 CMake 文件以支持编译环境。以下是标准的 CMake 配置文件示例[^2]: ```cmake cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(octree_change_detection) find_package(PCL 1.2 REQUIRED) include_directories(${PCL_INCLUDE_DIRS}) link_directories(${PCL_LIBRARY_DIRS}) add_definitions(${PCL_DEFINITIONS}) add_executable(octree_change_detection octree_change_detection.cpp) target_link_libraries(octree_change_detection ${PCL_LIBRARIES}) ``` 此配置确保项目能够正确链接到 PCL 库并加载必要的头文件和定义。 --- #### 八叉树初始化与设置参数 在实际应用中,可以通过以下方式创建并初始化八叉树对象: ```cpp #include <pcl/point_cloud.h> #include <pcl/octree/octree_pointcloud_changedetector.h> // 定义点类型 typedef pcl::PointXYZ PointT; int main() { // 创建点云实例 pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>); // 设置分辨率(即每个体素的边长) double resolution = 0.1; // 初始化八叉树对象 pcl::octree::OctreePointCloudChangeDetector<PointT> octree(resolution); } ``` 上述代码片段展示了如何指定八叉树的分辨率以及初始化过程[^1]。 --- #### 添加点云至八叉树 将初始点云添加到八叉树中以便后续对比操作: ```cpp // 将点云插入到八叉树 octree.setInputCloud(cloud); octree.addPointsFromInputCloud(); // 更新当前状态作为参考帧 octree.switchBuffers(); ``` 这里的关键步骤是调用 `switchBuffers()` 方法保存当前点云的状态,从而允许未来的新点云与其进行差异分析。 --- #### 对比新旧点云 当有新的点云到达时,可以将其加入同一棵八叉树并与之前的记录做对比: ```cpp // 假设 new_cloud 是更新后的点云集 pcl::PointCloud<PointT>::Ptr new_cloud(new pcl::PointCloud<PointT>()); new_cloud->points.push_back(PointT(x, y, z)); // 示例点坐标填充逻辑省略 // 清空现有缓存并将新点集载入 octree.setInputCloud(new_cloud); octree.addPointsFromInputCloud(); // 获取发生变化的位置集合 std::vector<int> added_indices; std::vector<int> removed_indices; octree.getAddedPointsIndices(added_indices); // 新增点索引列表 octree.getDeletedPointsIndices(removed_indices); // 移除点索引列表 ``` 以上部分实现了动态监测场景中的物体移动或消失现象的功能。 --- #### 可选扩展:查询特定区域信息 如果需要进一步探索某一体素的具体属性,则可通过如下接口完成: - **检查某个位置是否有对应体素存在** - **获取整棵树的最大深度** - **提取任意选定体素中心的世界坐标** 这些辅助工具均已在官方文档第六章节有所描述。 --- ### 总结 综上所述,借助于 PCL 提供的强大 API 支持,开发者仅需少量代码即可高效达成复杂任务目标——实时追踪三维环境中发生的细微变动状况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值