You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 07:29:59