open3d提供了一个专门用于八叉树的数据结构 Octree。
class Octree(Geometry3D):
max_depth
origin
root_node
size
def convert_from_point_cloud(self, point_cloud, size_expand=0.01):
def create_from_voxel_grid(self):
def insert_point(self, point, f_init, f_update, fi_init=None, fi_update=None):
def is_point_in_bound(self, point, origin, size):
# 当前节点的子节点
def locate_leaf_node(self, point):
def to_voxel_grid(self):
def traverse(self, f, *args, **kwargs):
class OctreeInternalPointNode(OctreeInternalNode):
children # 子节点
indices # 下标
def __init__(self, *args, **kwargs):
"""
__init__(*args, **kwargs)
Overloaded function.
1. __init__(self)
Default constructor
2. __init__(self, arg0)
Copy constructor
Args:
arg0 (open3d.geometry.OctreeInternalPointNode)
"""
def get_init_function(self):
def get_update_function(self, arg0):
def __copy__(self):
def __deepcopy__(self, arg0):
class OctreeNodeInfo(__pybind11_builtins.pybind11_object):
child_index
depth
origin
size
def __init__(self, origin, size, depth, child_index):
"""
__init__(self, origin, size, depth, child_index)
Args:
origin (numpy.ndarray[float64[3, 1]])
size (float)
depth (int)
child_index (int)
"""
import open3d as o3d
import numpy as np
from open3d.web_visualizer import draw
from open3d.visualization import draw_geometries
pcd = o3d.io.read_point_cloud('datas/sphere.ply')
print(pcd)
-> PointCloud with 642 points.
draw(pcd)
1. 从点云构建八叉树
oct = o3d.geometry.Octree(max_depth=4)
oct.convert_from_point_cloud(pcd)
print(oct)
-> Octree with origin: [-1, -1, -1], size: 2.02, max_depth: 4
draw(oct)


print(oct.root_node)
-> OctreeInternalPointNode with 8 non-empty child nodes and 642 points
print(oct.root_node.children[0])
-> OctreeInternalPointNode with 7 non-empty child nodes and 93 points
2. 八叉树索引
# 取八叉树第一层的第四部分中的点云,涂成红色
oct_4 = pcd.select_by_index(oct.root_node.children[4].indices)
oct_4.paint_uniform_color([1,0,0])
oct_e = pcd.select_by_index(oct.root_node.children[4].indices, True)
oct_e.paint_uniform_color([0,0,0])
draw([oct_4, oct_e])


# 返回指定点在八叉树中的叶节点 以及该点所在的内部节点信息
leafnode, nodeinfo = oct.locate_leaf_node(pcd.points[0])
print(leafnode)
-> OctreePointColorLeafNode with color [0, 0, 0] containing 1 points.
print(nodeinfo) #
-> OctreeNodeInfo with origin [0.38875, 0.89375, 0.01], size 0.12625, depth 4, child_index 3
print(pcd.points[0]) # 第一个点的坐标
-> [0.39960703 0.91298246 0.08232358]
print(oct.origin) # 八叉树坐标轴最小值
-> [-1. -1. -1.]
print(oct.size) # 八叉树
-> 2.02
2. 八叉树回调
def callback(node, node_info):
if isinstance(node, o3d.geometry.OctreeInternalNode): # 内部节点
if isinstance(node, o3d.geometry.OctreeInternalPointNode):
# for child in node.children:
depth = node_info.depth
child_num = len([child for child in node.children if child is not None])
point_num = len(node.indices)
print('{} depth: {} | index: {} | child num: {} | point num: {}'.format('- '*depth, depth, node_info.child_index, child_num, point_num))
if isinstance(node, o3d.geometry.OctreeLeafNode): # 叶节点
if isinstance(node, o3d.geometry.OctreePointColorLeafNode):
pass
oct.traverse(callback)
depth: 0 | index: 0 | child num: 8 | point num: 642
- depth: 1 | index: 0 | child num: 7 | point num: 93
- - depth: 2 | index: 0 | child num: 1 | point num: 3
- - - depth: 3 | index: 7 | child num: 3 | point num: 3
- - depth: 2 | index: 1 | child num: 6 | point num: 14
- - - depth: 3 | index: 2 | child num: 1 | point num: 1
- - - depth: 3 | index: 3 | child num: 2 | point num: 4
- - - depth: 3 | index: 4 | child num: 1 | point num: 1
- - - depth: 3 | index: 5 | child num: 2 | point num: 3
- - - depth: 3 | index: 6 | child num: 3 | point num: 3
- - - depth: 3 | index: 7 | child num: 2 | point num: 2
- - depth: 2 | index: 2 | child num: 6 | point num: 14
......