如何使用Open3D提取三维模型体素网格的最底层体素
提取体素网格最底层体素实现方案
你的实现思路逻辑是成立的:遍历所有体素找到Z轴全局最小值,再筛选出所有Z坐标匹配该值的体素即可得到最底层结果,但现有代码存在两处会直接导致运行异常或结果错误的问题:
- 语法错误:
voxel_center是Python原生列表,不支持voxel_center[i, 2]这类numpy风格的二维索引,运行时会直接抛出类型错误 - 逻辑错误:第二个遍历循环中,
ind变量仅在匹配到最低层体素时才自增,会导致voxels[ind]取到错误位置的体素,返回的网格索引和实际最低层体素不对应
除此之外原代码可以做效率优化:不需要单独遍历一轮存储所有体素的中心坐标,减少不必要的内存占用;体素坐标为浮点数,直接用等值判断容易因计算精度误差漏选,需要增加微小容差。
基础可运行版本
逻辑清晰,适合小体量体素网格:
from open3d.geometry import VoxelGrid import numpy as np def find_lowest_voxel_indices(voxel_grid: VoxelGrid) -> list: voxels = voxel_grid.get_voxels() if not voxels: return [] min_z = float("inf") # 第一轮遍历确定全局最小Z值 for voxel in voxels: center_z = voxel_grid.get_voxel_center_coordinate(voxel.grid_index)[2] if center_z < min_z: min_z = center_z lowest_indices = [] # 第二轮遍历筛选所有最低层体素 for voxel in voxels: center_z = voxel_grid.get_voxel_center_coordinate(voxel.grid_index)[2] # 浮点数比较增加容差,避免精度问题漏选 if np.abs(center_z - min_z) < 1e-6: lowest_indices.append(voxel.grid_index) return lowest_indices # 调用示例 # 1. 读取Armadillo网格模型 # mesh = o3d.io.read_triangle_mesh("armadillo.ply") # 2. 生成体素网格 # voxel_grid = o3d.geometry.VoxelGrid.create_from_triangle_mesh(mesh, voxel_size=0.01) # 3. 提取最底层体素索引 # bottom_voxels = find_lowest_voxel_indices(voxel_grid)
高性能版本
适合百万级以上体量的大体素网格,借助numpy向量化计算提升运行效率:
def find_lowest_voxel_indices_fast(voxel_grid: VoxelGrid) -> list: voxels = voxel_grid.get_voxels() if not voxels: return [] # 批量读取所有体素中心坐标转numpy数组 all_centers = np.array([ voxel_grid.get_voxel_center_coordinate(v.grid_index) for v in voxels ]) min_z = all_centers[:, 2].min() # 布尔索引一次性筛选符合条件的体素 match_mask = np.abs(all_centers[:, 2] - min_z) < 1e-6 return [voxels[idx].grid_index for idx in np.where(match_mask)[0]]
使用说明
- 容差阈值
1e-6可以根据你设置的体素大小灵活调整,只要小于单个体素在Z轴方向的尺寸即可 - 如果你的坐标系定义中Z轴向上为正,上述代码返回的就是模型最底部的体素层;如果需要提取最顶层,把查找最小值的逻辑替换为查找最大值即可
- 需要验证结果时,可以给筛选出的最低层体素设置单独的高亮颜色,和原体素网格叠加渲染即可直观看到提取效果
内容的提问来源于stack exchange,提问作者Kevin Liu
相关产品推荐
相关产品推荐

