目录
1. 从点云中创建octree
2. 从体素网格中创建octree
3. 遍历octree
1. 从点云中创建octree
octree_find_leaf.py
convert_from_point_cloud
建立octree,查询点云中某个点在octree中哪个叶子节点。
# ----------------------------------------------------------------------------
# -                        Open3D: www.open3d.org                            -
# ----------------------------------------------------------------------------
# Copyright (c) 2018-2023 www.open3d.org
# SPDX-License-Identifier: MIT
# ----------------------------------------------------------------------------
import open3d as o3d
import numpy as np
if __name__ == "__main__":
    # 1. read mesh data
    N = 2000
    armadillo_data = o3d.data.ArmadilloMesh()
    pcd = o3d.io.read_triangle_mesh(
        armadillo_data.path).sample_points_poisson_disk(N)
    # 2. preprocess
    # 2.1 Fit to unit cube.
    pcd.scale(scale=1 / np.max(pcd.get_max_bound() - pcd.get_min_bound()),
              center=pcd.get_center())
    # 2.2 paint random color
    pcd.colors = o3d.utility.Vector3dVector(np.random.uniform(0, 1, size=(N, 3)))
    # 3. 建立Octree. 细分深度是4
    octree = o3d.geometry.Octree(max_depth=4)
    octree.convert_from_point_cloud(pcd, size_expand=0.01)
    # 4. view octree
    print('Displaying input octree ...')
    o3d.visualization.draw([octree])
    print('Finding leaf node containing the first point of pointcloud ...')
    print(octree.locate_leaf_node(pcd.points[0]))  # 点在哪个叶子节点
    # open3d.geometry.OctreeLeafNode, open3d.geometry.OctreeNodeInfo
    # (OctreePointColorLeafNode with color [0.315858, 0.264051, 0.780834] containing 1 points.,
    # OctreeNodeInfo with origin [-2.64148, 31.714, 2.07972], size 0.063125, depth 4, child_index 4)
view octree
2. 从体素网格中创建octree
octree_from_voxel_grid.py
create_from_voxel_grid
import open3d as o3d
import numpy as np
if __name__ == "__main__":
    # 1. read pcd
    N = 2000
    armadillo_data = o3d.data.ArmadilloMesh()
    pcd = o3d.io.read_triangle_mesh(
        armadillo_data.path).sample_points_poisson_disk(N)
    # Fit to unit cube.
    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)))
    # 2. create voxel grid
    print('Displaying input voxel grid ...')
    voxel_grid = o3d.geometry.VoxelGrid.create_from_point_cloud(pcd,
                                                                voxel_size=0.05)
    o3d.visualization.draw([voxel_grid])
    # 3. create octree from voxel grid
    octree = o3d.geometry.Octree(max_depth=4)
    octree.create_from_voxel_grid(voxel_grid)
    print('Displaying octree ..')
    o3d.visualization.draw([octree])

voxel_grid octree
3. 遍历octree
octree.traverse(f=f_traverse)
import open3d as o3d
import numpy as np
def f_traverse(node, node_info):
    early_stop = False
    # 1. 当前节点为内部节点
    if isinstance(node, o3d.geometry.OctreeInternalNode):
        # OctreeInternalNode class, containing OctreeNode children.
        if isinstance(node, o3d.geometry.OctreeInternalPointNode):
            # OctreeInternalPointNode class is an OctreeInternalNode
            # with a list of point indices (from point cloud) belonging to children of this node.
            # 1.1 计算当前内部节点的子节点个数
            n = 0
            for child in node.children:
                if child is not None:
                    n += 1
            # 1.2 打印当前内部节点node_info
            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  # 子节点数量小于250的,停止遍历该分支。
    # 2. 当前节点为叶子节点
    elif isinstance(node, o3d.geometry.OctreeLeafNode):
        if isinstance(node, o3d.geometry.OctreePointColorLeafNode):  # ColorLeafNode
            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
if __name__ == "__main__":
    # 1.read pcd
    N = 2000
    armadillo_data = o3d.data.ArmadilloMesh()
    pcd = o3d.io.read_triangle_mesh(
        armadillo_data.path).sample_points_poisson_disk(N)
    # Fit to unit cube.
    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)))
    # 2. create octree
    octree = o3d.geometry.Octree(max_depth=4)
    octree.convert_from_point_cloud(pcd, size_expand=0.01)
    print('Displaying input octree ...')
    o3d.visualization.draw([octree])
    # 3. traversing octree
    print('Traversing octree ...')
    octree.traverse(f=f_traverse)  # f_traverse是自定义的遍历函数。


















