目录
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是自定义的遍历函数。