Open3d之八叉树(Octree)

简介

八叉树是一种树数据结构,其中每个内部节点都有八个子节点。八叉树通常用于三维点云的空间划分。 八叉树的非空叶节点包含一个或多个属于同一空间细分的点。 八叉树是一个有用的三维空间描述,可以用来快速找到附近的点。 Open3D的几何类型Octree,可用于创建,搜索和遍历具有用户指定的最大树深度max_depth的八叉树。

从点云中构造八叉树

可以使用convert_from_point_cloud方法从点云中构造八叉树。通过沿着从根节点到深度max_depth处的相应叶节点的路径将每个点插入到树中。 随着树的深度增加,内部(最终是叶子)节点表示3D空间的较小划分。

如果点云具有颜色,则相应的叶节点采用最后插入的点的颜色。 size_expand参数增加了根八叉树节点的大小,因此它比原始点云边界稍大以容纳所有点。

 

# -*- coding: UTF-8 -*-
import numpy as np
import open3d as o3d
import Open3D.examples.python.open3d_tutorial as o3dtut

# 加载点云,并采样2000个点
N = 2000
pcd = o3dtut.get_armadillo_mesh().sample_points_poisson_disk(N)
# 点云归一化
pcd.scale(1 / np.max(pcd.get_max_bound() - pcd.get_min_bound()),
          center=pcd.get_center())
# 点云着色
pcd.colors = o3d.utility.Vector3dVector(np.random.uniform(0, 1, size=(N, 3)))
# 可视化
o3d.visualization.draw_geometries([pcd])

# 创建八叉树, 树深为4
octree = o3d.geometry.Octree(max_depth=4)
# 从点云中构建八叉树,适当扩展边界0.01m
octree.convert_from_point_cloud(pcd, size_expand=0.01)
# 可视化
o3d.visualization.draw_geometries([octree])

从体素网格中构造八叉树

也可以使用create_from_voxel_grid方法从Open3DVoxelGrid几何结构中构造八叉树。 输入VoxelGrid的每个体素都被视为3D空间中的一个点,其坐标对应于该体素的原点。 每个叶节点都采用其相应体素的颜色。

# 从点云中创建体素网格, 体素大小为0.05m
voxel_grid = o3d.geometry.VoxelGrid.create_from_point_cloud(pcd, voxel_size=0.05)
# 体素可视化
o3d.visualization.draw_geometries([voxel_grid])

# 创建八叉树, 树深为4
octree = o3d.geometry.Octree(max_depth=4)
# 从体素网格中构建八叉树
octree.create_from_voxel_grid(voxel_grid)
# 可视化
o3d.visualization.draw_geometries([octree])

另外,可使用to_voxel_gridOctree转变为VoxelGrid

遍历八叉树

可以遍历八叉树,这对于搜索或处理3D几何体的子部分很有用。通过向traverse方法提供回调,每次访问节点(内部或叶)时,都可以执行额外的处理。

在下面的示例中,提前停止标准仅用于处理具有超过特定点数的内部/叶节点。这种提前停止能力可以有效地处理满足一定条件的空间区域。

def f_traverse(node, node_info):
    early_stop = False

    if isinstance(node, o3d.geometry.OctreeInternalNode):
        if isinstance(node, o3d.geometry.OctreeInternalPointNode):
            n = 0
            for child in node.children:
                if child is not None:
                    n += 1
            print(
                "{}{}: Internal node at depth {} has {} children and {} points ({})"
                .format('    ' * node_info.depth,
                        node_info.child_index, node_info.depth, n,
                        len(node.indices), node_info.origin))

            # we only want to process nodes / spatial regions with enough points
            early_stop = len(node.indices) < 250
    elif isinstance(node, o3d.geometry.OctreeLeafNode):
        if isinstance(node, o3d.geometry.OctreePointColorLeafNode):
            print("{}{}: Leaf node at depth {} has {} points with origin {}".
                  format('    ' * node_info.depth, node_info.child_index,
                         node_info.depth, len(node.indices), node_info.origin))
    else:
        raise NotImplementedError('Node type not recognized!')

    # early stopping: if True, traversal of children of the current node will be skipped
    return early_stop


# 创建八叉树, 树深为4
octree = o3d.geometry.Octree(max_depth=4)
# 从点云中创建体素网格, 体素大小为0.01m
octree.convert_from_point_cloud(pcd, size_expand=0.01)
# 遍历
octree.traverse(f_traverse)

查找包含点的叶节点

使用上述遍历机制,可以快速地在八叉树中搜索包含给定点的叶节点。 通过locate_leaf_node方法提供此功能。

octree.locate_leaf_node(pcd.points[0])

 

  • 3
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
Open3D是一个用于3D数据处理的开源库,支持许多3D数据操作和算法。开发者可以使用Open3D来处理点云数据、三维重建、图形可视化等。 在Open3D八叉树是一种常用的数据结构,用于管理和索引3D空间的点云数据。八叉树将空间划分为一个个小的立方体单元,每个立方体单元称为一个节点。每个节点可以进一步分割成8个子节点,这样一级一级的分割下去,最终形成了一棵树结构。 遍历八叉树是指按照某种方式访问树的每一个节点。在Open3D,可以通过调用`octree.access()`函数来实现遍历八叉树。`octree.access()`函数通常需要传入一个callback函数作为参数,用于对每一个节点进行具体的操作。 以下是一个简单的遍历八叉树的例子: ```python import open3d as o3d def print_node(node): print(node) def main(): pcd = o3d.io.read_point_cloud("cloud.ply") octree = o3d.geometry.Octree(max_depth=5) octree.convert_from_point_cloud(pcd) octree.access(print_node) if __name__ == "__main__": main() ``` 在这个例子,首先使用`o3d.io.read_point_cloud()`函数读取一个点云数据文件。然后,创建一个八叉树实例,并使用`convert_from_point_cloud()`函数将点云数据转换为八叉树。 接下来,定义一个名为`print_node()`的callback函数,用于打印每个节点。最后,通过调用`octree.access(print_node)`函数来遍历八叉树,并将每个节点传递给callback函数进行处理。 这是一个简单的遍历八叉树的例子,实际应用可能需要根据具体需求对每个节点进行更复杂的操作和处理。希望这个回答能够帮助到您。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值