使用Open3D显示3DShapeNet体素数据遇AttributeError问题咨询
Open3D显示ShapeNet体素报错的解决方法
问题场景
加载Princeton 3DShapeNet数据集的飞机体素文件,通过matplotlib可正常显示,但使用Open3D的VoxelGrid显示时触发错误:
AttributeError: 'open3d.cuda.pybind.geometry.VoxelGrid' object has no attribute 'voxels'
原代码:
import scipy.io import numpy as np import matplotlib.pyplot as plt import open3d as o3d import scipy.ndimage voxels = scipy.io.loadmat("3DShapeNets/volumetric_data/airplane/30/test/e5bf09ef0e8de9e8a9de7e2f11b2d506_9.mat")["instance"] voxels = np.pad(voxels, (1, 1), "constant", constant_values=(0, 0)) voxels = scipy.ndimage.zoom(voxels, (2, 2, 2), mode="constant", order=0) def PlotVoxels(voxels): fig = plt.figure() ax = fig.add_subplot(projection = '3d') ax.set_aspect('equal') ax.voxels(voxels, edgecolor="blue") plt.show() def PlotVoxels3D(voxels): voxel_grid = o3d.geometry.VoxelGrid() voxel_grid.voxels = o3d.utility.Vector3iVector(np.argwhere(voxels)) o3d.visualization.draw_geometries([voxel_grid]) PlotVoxels(voxels) PlotVoxels3D(voxels)
错误原因
Open3D的VoxelGrid类没有公开可直接赋值的voxels属性,无法通过直接赋值的方式添加体素,必须使用官方提供的API方法创建或添加体素。
修复方案
以下两种方式可正确创建VoxelGrid:
方法1:从点云转换创建(高效适合大规模数据)
先将非零体素坐标转为点云,再基于点云创建VoxelGrid,设置匹配的体素大小:
def PlotVoxels3D(voxels): # 获取所有非零体素的坐标 voxel_coords = np.argwhere(voxels) # 转换为Open3D点云格式 pcd = o3d.geometry.PointCloud() pcd.points = o3d.utility.Vector3dVector(voxel_coords.astype(np.float64)) # 创建VoxelGrid,体素大小设为1匹配原数据尺寸 voxel_grid = o3d.geometry.VoxelGrid.create_from_point_cloud_within_bounds( pcd, voxel_size=1.0, min_bound=voxel_coords.min(axis=0) - 0.5, max_bound=voxel_coords.max(axis=0) + 0.5 ) o3d.visualization.draw_geometries([voxel_grid])
方法2:手动添加体素(逻辑直观适合小体量数据)
遍历所有非零体素,逐个添加到VoxelGrid中:
def PlotVoxels3D(voxels): voxel_grid = o3d.geometry.VoxelGrid() # 设置体素网格边界与尺寸 min_bound = np.array([0, 0, 0]) max_bound = np.array(voxels.shape) voxel_grid.origin = min_bound - 0.5 # 偏移原点让体素居中显示 voxel_grid.voxel_size = 1.0 # 逐个添加非零体素 for coord in np.argwhere(voxels): voxel = o3d.geometry.Voxel(o3d.utility.Vector3iVector([coord])[0]) voxel_grid.add_voxel(voxel) o3d.visualization.draw_geometries([voxel_grid])
内容的提问来源于stack exchange,提问作者nowsqwhat
相关产品推荐
相关产品推荐

