PyTorch3D 数据集加载指南:ShapeNetCore 与 R2N2 数据加载器深度解析
2026/9/24 13:35:29 网站建设 项目流程
  • 人工智能
  • 深度学习
  • 计算机视觉
  • 图形学

【免费下载链接】pytorch3d

PyTorch3D is FAIR's library of reusable components for deep learning with 3D data

项目地址:https://gitcode.com/gh_mirrors/py/pytorch3d
点击查看免费下载

本文是 PyTorch3D 官方数据加载笔记(docs/notes/datasets.md)的完整技术指南,系统讲解两大常用 3D 数据集ShapeNetCoreR2N2的加载、批处理与可微渲染实践。读者将掌握ShapeNetCoreR2N2两个数据加载类的构造参数、__getitem__返回的数据字典结构、配套的collate_fn批处理函数,以及内置render函数的四种模型选取方式,并了解其与 PyTorch3DMeshes结构与可微渲染管线的衔接原理。

在 PyTorch3D 的三维深度学习工作流中,数据加载是连接原始 CAD 模型与网格操作、渲染、损失计算的第一步。PyTorch3D 在 pytorch3d/datasets/ 目录下为两个最常用的公开数据集提供了开箱即用的torch.utils.data.Dataset实现:ShapeNetCore(位于 pytorch3d/datasets/shapenet/shapenet_core.py)与R2N2(位于 pytorch3d/datasets/r2n2/r2n2.py)。二者共享一个抽象基类ShapeNetBase(位于 pytorch3d/datasets/shapenet_base.py),该基类实现了纹理加载、渲染参数解析、类别随机采样等公共逻辑。

ShapeNetCore 数据加载器

数据集背景与版本差异

ShapeNet 是一个包含三维 CAD 模型的大型数据集,ShapeNetCore 是其中的一个子集,可从 ShapeNet 官网申请下载。ShapeNetCore 共有两个版本,两者在类别数量与文件组织方式上存在差异(以下信息以当前仓库源码中的文档字符串为准,见 pytorch3d/datasets/shapenet/shapenet_core.py 中ShapeNetCore.__init__的说明):

  • v1:包含 57 个类别,每个模型存放为model.obj文件。注意 v1 中有两个类别——02858304(boat,船)与02992529(cellphone,手机)——分别是04530566(watercraft,水上交通工具)与04401088(telephone,电话)的下位词(hyponym),如需合并可按需自行处理。
  • v2:包含 55 个类别,与 v1 相比缺少02858304(boat)与02834778(bicycle,自行车)两个类别,模型存放为models/model_normalized.obj文件。

在源码中,两个版本的模型文件路径通过self.model_dir区分:"model.obj" if version == 1 else "models/model_normalized.obj"。类别编号与标签的映射表分别存放在 pytorch3d/datasets/shapenet/shapenet_synset_dict_v1.json 与 pytorch3d/datasets/shapenet/shapenet_synset_dict_v2.json 中,加载时根据version参数自动选择对应字典文件。

ShapeNetCore 类与构造参数

ShapeNetCore继承自torch.utils.data.Dataset,构造时接收本地数据集路径,并遍历目录加载其中所有模型。其构造函数签名与各参数含义如下(详见 pytorch3d/datasets/shapenet/shapenet_core.py):

参数类型默认值说明
data_dirstr必填ShapeNetCore 数据在本地的存放路径
synsetsList[str]None要加载的类别列表,可用 synset 编号(如"04330267")或标签(如"guitar")表示,两者可混用;不指定时加载data_dir下所有官方映射中的类别
versionint1ShapeNetCore 版本,仅允许12,传入其他值会抛出ValueError("Version number must be either 1 or 2.")
load_texturesboolTrue是否加载模型纹理;为True时纹理以TexturesAtlas类型返回(每个面一张纹理图)
texture_resolutionint4每个面创建的纹理图分辨率,将生成(texture_resolution, texture_resolution, 3)的纹理图

目录结构的约定为:data_dir / <synset_id> / <model_id> / model.obj(v1),即每个模型的model_id是其所在子目录的名称。构造时会校验传入的类别是否存在(不存在则发出warnings.warn),并建立synset_start_idxs(各类别起始索引)与synset_num_models(各类别模型数量)映射,供后续按类别采样使用。

一个典型用法:

from pytorch3d.datasets import ShapeNetCore # 加载整个 ShapeNetCore v1 数据集 shapenet_dataset = ShapeNetCore(data_dir="/path/to/ShapeNetCore.v1", version=1) # 只加载部分类别(混用编号与标签) shapenet_subset = ShapeNetCore( data_dir="/path/to/ShapeNetCore.v1", synsets=["04330267", "guitar", "02801938", "birdhouse", "03991062", "tower"], version=1, ) # 不加载纹理 shapenet_no_texture = ShapeNetCore( data_dir="/path/to/ShapeNetCore.v1", load_textures=False, version=1 )

getitem返回的数据结构

通过索引访问数据集时,ShapeNetCore.__getitem__返回一个字典(见 pytorch3d/datasets/shapenet/shapenet_core.py),包含以下键:

  • vertsFloatTensor,形状(V, 3),网格顶点坐标;
  • facesLongTensor,形状(F, 3),三角面片的顶点索引;
  • synset_id:str,类别编号;
  • model_id:str,模型编号;
  • label:str,类别标签(由 synset 字典反查得到);
  • texturesload_textures=True时为TexturesAtlas纹理((F, texture_resolution, texture_resolution, 3)),否则为None

底层的网格加载由基类ShapeNetBase._load_mesh完成(见 pytorch3d/datasets/shapenet_base.py):它调用pytorch3d.io.load_obj,并传入create_texture_atlasload_texturestexture_atlas_size三个参数;若某个模型没有纹理,会自动生成一张白色纹理图(全 1 张量),保证后续渲染不因缺纹理而失败。

通过 collate_batched_meshes 构造批处理

ShapeNetCore 加载的模型可以直接交给torch.utils.data.DataLoader使用,但需要配合 PyTorch3D 定制的collate_fncollate_batched_meshes,它位于 pytorch3d/datasets/utils.py(并从 pytorch3d/datasets/init.py 导出)。

该函数的作用是:将一批__getitem__返回的字典列表合并为一个字典,其中每个键对应一个列表;更重要的是,当批数据同时包含vertsfaces时,会用它们构造一个批量的Meshes对象(纹理若存在则以TexturesAtlas传入),作为collated_dict["mesh"]返回。Meshes是 PyTorch3D 的核心网格表示(定义于 pytorch3d/structures/meshes.py),支持顶点/面片补齐(padding)、按批次广播,并可直接用于 PyTorch3D 的各种算子与渲染管线。

from torch.utils.data import DataLoader from pytorch3d.datasets import ShapeNetCore, collate_batched_meshes shapenet_dataset = ShapeNetCore(data_dir="/path/to/ShapeNetCore.v1") shapenet_core_loader = DataLoader( shapenet_dataset, batch_size=12, collate_fn=collate_batched_meshes ) batch = next(iter(shapenet_core_loader)) # batch["mesh"] 是一个 Meshes 对象,可直接参与渲染或几何运算 print(batch["mesh"].verts_padded().shape) # (12, V_max, 3) print(batch["mesh"].faces_padded().shape) # (12, F_max, 3)

在 tests/test_shapenet_core.py 的test_collate_models中,可以找到对collate_batched_meshes形状、类型以及 DataLoader 输出批次结构的完整验证。

内置 render 函数:按需渲染模型

ShapeNetCore(通过基类ShapeNetBase.render,见 pytorch3d/datasets/shapenet_base.py)还提供了一个定制化的render方法,可以用 PyTorch3D 的可微渲染器渲染指定模型,支持四种选取方式:

  1. model_ids(List[str]):渲染这些模型编号对应的模型;
  2. categories+sample_nums:从每个给定类别中随机采样sample_nums指定的模型数量进行渲染(sample_nums可与类别一一对应,也可只给一个整数自动广播);
  3. idxs(List[int]):渲染给定索引的模型(会校验索引是否越界);
  4. 什么都不指定:随机采样sample_nums中第一个数(默认为 1)个模型渲染。

render的完整签名还包括:

  • shader_type:着色器类型,可选HardPhongShader(默认)、SoftPhongShaderHardGouraudShaderSoftGouraudShaderHardFlatShaderSoftSilhouetteShader等;
  • device:张量所在设备(str 或torch.device);
  • **kwargs:接受渲染器支持的所有参数,如camerasraster_settingslights等。

渲染内部流程为:先通过_handle_render_inputs将选取方式转换为模型索引列表(见 pytorch3d/datasets/shapenet_base.py),再调用__getitem__加载网格并用collate_batched_meshes拼装成批量Meshes;若网格没有纹理则补一个全 1 的TexturesVertex;默认相机为FoVPerspectiveCameras;最后构建MeshRendererMeshRasterizer+ 指定shader_type的着色器)输出形状为(N, H, W, 3)的图像批次。若传入多个相机,网格会被extend广播,使每个模型在多个视角下各渲染一次;当相机数量与网格数量不匹配时,会抛出ValueError("Mismatch between batch dims of cameras and meshes.")

类别采样底层使用torch.multinomial实现(见_sample_idxs_from_category),当采样数大于类别内模型数时会放回采样并发出警告。测试 tests/test_shapenet_core.py 中的test_render_shapenet_core展示了三种典型调用:

import torch from pytorch3d.datasets import ShapeNetCore from pytorch3d.renderer import FoVPerspectiveCameras, PointLights, RasterizationSettings, look_at_view_transform device = torch.device("cuda:0") torch.manual_seed(39) piano_dataset = ShapeNetCore("/path/to/ShapeNetCore.v1", synsets=["piano"]) R, T = look_at_view_transform(1.0, 1.0, 90) cameras = FoVPerspectiveCameras(R=R, T=T, device=device) raster_settings = RasterizationSettings(image_size=512) lights = PointLights( location=torch.tensor([0.0, 1.0, -2.0], device=device)[None], diffuse_color=((0, 0, 0),), specular_color=((0, 0, 0),), device=device, ) # 按索引渲染 pianos = piano_dataset.render( idxs=list(range(3)), device=device, cameras=cameras, raster_settings=raster_settings, lights=lights, ) # shape (3, H, W, 3) # 按 model_ids 渲染 pianos_by_ids = piano_dataset.render( model_ids=["13394ca47c89f91525a3aaf903a41c90", "14755c2ee8e693aba508f621166382b0", "156c4207af6d2c8f1fdc97905708b8ea"], device=device, cameras=cameras, raster_settings=raster_settings, lights=lights, ) # 按类别随机采样渲染 mixed = piano_dataset.render( categories=["faucet", "chair"], sample_nums=[2, 1], device=device, cameras=cameras, raster_settings=raster_settings, lights=lights, )

R2N2 数据加载器

数据集背景

R2N2(3D-R2N2,源自斯坦福大学)数据集包含 13 个类别,是 ShapeNetCore v1 的子集。与 ShapeNetCore 相比,R2N2 还额外提供:

  • 每个物体的24 张不同视角渲染图(由 Blender 渲染);
  • 每个物体的体素化(voxelized)模型

绝大多数模型的 24 个视角都落在同一个 train/val/test 划分中,但有 8 个模型的视角被拆分到了 train 与 test 两个划分里。R2N2 数据可从其官方页面下载,官方同时提供划分文件(splits file)。

R2N2 类与构造参数

R2N2同样继承自torch.utils.data.Dataset,其构造函数(见 pytorch3d/datasets/r2n2/r2n2.py)比ShapeNetCore需要更多路径参数:

参数类型默认值说明
splitstr必填数据划分,必须是"train""val""test"之一,否则抛出ValueError
shapenet_dirstr必填ShapeNetCore v1 数据路径
r2n2_dirstr必填R2N2 数据集路径
splits_filestr必填包含 train/val/test 划分的 JSON 文件路径
return_all_viewsboolTrue是否加载划分内的所有视角;设为False时每个模型随机选取一个视角
return_voxelsboolFalse是否返回体素张量(形状(D, D, D)
views_rel_pathstr"ShapeNetRendering"R2N2 渲染图在r2n2_dir下的相对路径;若该目录缺失,渲染图会被跳过(并发出警告)
voxels_rel_pathstr"ShapeNetVoxels"R2N2 体素数据在r2n2_dir下的相对路径;若缺失,体素会被跳过
load_texturesboolTrue是否加载网格纹理
texture_resolutionint4每面纹理图分辨率

构造时会读取splits_file中对应split的划分字典,逐类别、逐模型检查其在shapenet_dir中是否存在,并记录每个模型可用的视角列表(views_per_model_list)。初始化完成后,还会在终端以表格形式打印每个类别的实例数量汇总(通过tabulate)。

典型用法:

from pytorch3d.datasets import R2N2 r2n2_dataset = R2N2( split="train", shapenet_dir="/path/to/ShapeNetCore.v1", r2n2_dir="/path/to/R2N2", splits_file="/path/to/splits.json", return_voxels=True, )

getitem返回的数据结构

R2N2.__getitem__(model_idx, view_idxs=None)返回的字典在ShapeNetCore的基础上(vertsfacessynset_idmodel_idlabeltextures)额外包含(见 pytorch3d/datasets/r2n2/r2n2.py):

  • imagesFloatTensor,形状(V, H, W, C),其中V为返回的视角数量,为 R2N2 提供的原始渲染图(像素值归一化到[0, 1]);
  • RFloatTensor,形状(V, 3, 3),旋转矩阵;
  • TFloatTensor,形状(V, 3),平移向量;
  • KFloatTensor,形状(V, 4, 4),内参矩阵(来自 Blender,略作调整以适配 PyTorch3D 世界坐标系,源码中写死为固定张量);
  • voxelsFloatTensor,形状(V, D, D, D),体素张量(仅当return_voxels=True且体素文件存在时返回)。

view_idxs参数允许按需只取部分视角:索引必须是该模型在当前 split 中可用的视角编号(范围通常在 0 到 23 之间);若传入的索引无效,则忽略并返回全部已加载视角(同时发出警告)。第二参数既可以整体传给__getitem__,也可以作为元组(model_idx, view_idxs)传入。

相机标定来源于每个模型rendering/rendering_metadata.txt中的azim, elev, yaw, dist_ratio, fov五个参数:距离由dist_ratio * MAX_CAMERA_DISTANCEMAX_CAMERA_DISTANCE = 1.75,取自 R2N2 官方常量)计算,外参矩阵由compute_extrinsic_matrix(见 pytorch3d/datasets/r2n2/utils.py)根据方位角、仰角、距离构造,再经_compute_camera_calibration转换到 PyTorch3D 世界坐标系得到RT

体素读取链路为:read_binvox_coords解析.binvox文件(pytorch3d/datasets/r2n2/utils.py)得到非零体素坐标,align_bbox将体素包围盒对齐到网格顶点坐标系,最后voxelize结合 Blender 内参与外参矩阵投影,输出128 × 128 × 128VOXEL_SIZE = 128)的体素张量(pytorch3d/datasets/r2n2/utils.py)。tests/test_r2n2.py 的test_load_R2N2对上述各字段的形状进行了逐项断言,例如默认返回 24 个视角、图像形状为(24, 137, 137, 3)、体素形状为(24, 128, 128, 128)

通过 collate_batched_R2N2 构造批处理

与 ShapeNetCore 对应,R2N2 的定制collate_fncollate_batched_R2N2(位于 pytorch3d/datasets/r2n2/utils.py)。它在collate_batched_meshes基础上继续处理:

  • images:若各模型视角数相同V,堆叠为(N, V, H, W, 3),否则退化为列表;
  • RTK:若视角数一致,分别堆叠为(N, V, 3, 3)(N, V, 3)(N, V, 4, 4)
  • voxels:堆叠为(N, V, S, S, S)S为体素尺寸),否则退化为列表。
from torch.utils.data import DataLoader from pytorch3d.datasets import R2N2, collate_batched_R2N2 r2n2_loader = DataLoader( r2n2_dataset, batch_size=12, collate_fn=collate_batched_R2N2 ) batch = next(iter(r2n2_loader)) # batch["mesh"] -> Meshes # batch["images"] -> (12, V, H, W, 3) # batch["R"] -> (12, V, 3, 3) # batch["T"] -> (12, V, 3) # batch["K"] -> (12, V, 4, 4) # batch["voxels"] -> (12, V, 128, 128, 128)

tests/test_r2n2.py 的test_collate_models验证了上述所有输出在 DataLoader 中的形状与类型。

render 函数与 BlenderCamera

R2N2.render(见 pytorch3d/datasets/r2n2/r2n2.py)继承并扩展了ShapeNetBase.render的能力。除model_idscategoriessample_numsidxsshader_typedevice**kwargs外,它新增了view_idxs参数:当不显式传入cameras时,默认使用BlenderCamera——一种专门为 R2N2 标定设计的相机类(定义于 pytorch3d/datasets/r2n2/utils.py),其投影变换直接由K内参矩阵构成——从而以与 R2N2 原始渲染完全一致的方向渲染指定视角。这在对比重建结果与真实渲染图时非常有用。

import torch from pytorch3d.datasets import R2N2 from pytorch3d.renderer import PointLights, RasterizationSettings device = torch.device("cuda:0") torch.manual_seed(39) r2n2_dataset = R2N2("train", SHAPENET_PATH, R2N2_PATH, SPLITS_PATH) raster_settings = RasterizationSettings(image_size=512) lights = PointLights( location=torch.tensor([0.0, 1.0, -2.0], device=device)[None], diffuse_color=((0, 0, 0),), specular_color=((0, 0, 0),), device=device, ) # 使用 R2N2 自身标定,以指定视角渲染 r2n2_batch = r2n2_dataset.render( idxs=torch.randint(1000, (2,)).tolist(), view_idxs=torch.randint(24, (2,)).tolist(), device=device, raster_settings=raster_settings, lights=lights, ) # shape (4, H, W, 3),2 个模型 × 2 个视角

render_cubified_voxels(pytorch3d/datasets/r2n2/utils.py)是配套的另一个实用函数:先用 PyTorch3D 的cubify算子(阈值为CUBIFY_THRESH = 0.2)把体素张量转换为网格,再以BlenderCamera渲染,方便直接可视化体素重建结果(tests/test_r2n2.py 的test_render_voxels有对应验证)。

数据加载的最佳实践与注意事项

综合两份数据加载器的实现与测试(tests/test_shapenet_core.py、tests/test_r2n2.py),在使用时有以下几点值得注意:

  1. 路径完整性ShapeNetCore只要求本地存在网格文件即可加载;R2N2则依赖shapenet_dir(网格)、r2n2_dir(渲染图与体素)与splits_file三者的对齐。若views_rel_pathvoxels_rel_path对应目录缺失,加载器不会报错,而是自动跳过相应数据并发出警告,因此训练前应检查r2n2_dataset.return_imagesreturn_voxels标志。
  2. 版本号校验ShapeNetCore(version=3)会直接抛出ValueError,版本只能是 1 或 2(tests/test_shapenet_core.py 的test_load_shapenet_core中对此有断言)。
  3. 渲染参数校验render对无效model_idValueError,对越界idxsIndexError;相机批量维度与网格批量维度不一致时抛ValueError,测试test_catch_render_arg_errors(R2N2 版本见 tests/test_r2n2.py)覆盖了这些分支。
  4. 纹理处理load_textures=False__getitem__返回的texturesNone(tests/test_shapenet_core.py 的test_load_textures_false验证了这一点),而render内部会对无纹理网格自动补全白色纹理,保证渲染路径始终可用。
  5. Meshes 批处理:务必使用对应的collate_fncollate_batched_meshes/collate_batched_R2N2)而非 PyTorch 默认的collate,否则无法获得可直接用于 PyTorch3D 算子与渲染器的Meshes对象。

小结

PyTorch3D 的ShapeNetCoreR2N2数据加载器把"下载数据集 → 解析 OBJ / 渲染图 / 体素 / 相机标定 → 构造Meshes批处理 → 可微渲染"整条链路封装为标准的torch.utils.data.Dataset接口。ShapeNetBase提供公共的纹理加载、索引解析与渲染骨架,两个子类分别针对纯网格数据(ShapeNetCore)与多视图 + 体素数据(R2N2)做了专门扩展,其中BlenderCamera与视角级标定使得研究者可以精确复现 R2N2 原始渲染视角,为单视图三维重建、视图合成、体素重建等任务提供了开箱即用的数据基础。更多文件读写能力可进一步阅读 docs/notes/io.md 与 docs/notes/meshes_io.md。

  • 人工智能
  • 深度学习
  • 计算机视觉
  • 图形学

【免费下载链接】pytorch3d

PyTorch3D is FAIR's library of reusable components for deep learning with 3D data

项目地址:https://gitcode.com/gh_mirrors/py/pytorch3d
点击查看免费下载
上一篇:【免费下载】 Vue大屏插件:Vue-Big-Screen-Plugin - 拓展你的Web可视化边界
下一篇:如何用VDesk提升多任务处理效率:Windows虚拟桌面工作流优化方案

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询