PyTorch3D

PyTorch3D

  • ドキュメント
  • チュートリアル
  • API
  • GitHub

›

チュートリアル

  • 概要

3D演算子

  • メッシュフィッティング
  • バンドル調整

レンダリング

  • テクスチャ付きメッシュのレンダリング
  • DensePoseメッシュのレンダリング
  • カラーポイントクラウドのレンダリング
  • レンダリングによるテクスチャ付きメッシュのフィッティング
  • 微分可能なレンダリングによるカメラ位置最適化
  • レイマーチングによるボリュームフィッティング
  • レイマーチングによる簡略化されたNeRFのフィッティング

データローダー

  • ShapeNetCoreとR2N2のデータローダー

Implicitron

  • Implicitronを用いたカスタムボリューム関数のトレーニング
  • Implicitron設定システムの詳細
Google Colabで実行
チュートリアルJupyter Notebookのダウンロード
チュートリアルソースコードのダウンロード
In [ ]
# Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved.

ShapeNetCoreとR2N2のデータローダー¶

このチュートリアルでは、以下の方法を示します。

  • PyTorch3Dのデータローダーを使用して、ShapeNetCoreとR2N2からモデルを読み込む方法。
  • 読み込んだデータセットを`torch.utils.data.DataLoader`に渡す方法。
  • PyTorch3Dのレンダラーを使用して、ShapeNetCoreモデルをレンダリングする方法。
  • データセット内の元のレンダリングと同じ向きで、R2N2モデルをレンダリングする方法。
  • R2N2モデルのボクセルを視覚化する方法。

0. モジュールのインストールとインポート¶

`torch`と`torchvision`がインストールされていることを確認してください。`pytorch3d`がインストールされていない場合は、次のセルを使用してインストールしてください。

In [ ]
import os
import sys
import torch
need_pytorch3d=False
try:
    import pytorch3d
except ModuleNotFoundError:
    need_pytorch3d=True
if need_pytorch3d:
    if torch.__version__.startswith("2.2.") and sys.platform.startswith("linux"):
        # We try to install PyTorch3D via a released wheel.
        pyt_version_str=torch.__version__.split("+")[0].replace(".", "")
        version_str="".join([
            f"py3{sys.version_info.minor}_cu",
            torch.version.cuda.replace(".",""),
            f"_pyt{pyt_version_str}"
        ])
        !pip install fvcore iopath
        !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html
    else:
        # We try to install PyTorch3D from source.
        !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'
In [ ]
import numpy as np
import torch

from pytorch3d.datasets import (
    R2N2,
    ShapeNetCore,
    collate_batched_meshes,
    render_cubified_voxels,
)
from pytorch3d.renderer import (
    OpenGLPerspectiveCameras,
    PointLights,
    RasterizationSettings,
    TexturesVertex,
    look_at_view_transform,
)

from pytorch3d.structures import Meshes
from torch.utils.data import DataLoader

# add path for demo utils functions 
import sys
import os
sys.path.append(os.path.abspath(''))

**Google Colab**を使用している場合は、画像グリッドをプロットするためのutilsファイルを取得してください。

In [ ]
!wget https://raw.githubusercontent.com/facebookresearch/pytorch3d/main/docs/tutorials/utils/plot_image_grid.py
from plot_image_grid import image_grid

または、ローカルで実行する場合は、次のセルのコメントを外して実行してください。

In [ ]
# from utils import image_grid

1. データセットの読み込み¶

ShapeNetCoreデータセットをまだダウンロードしていない場合は、こちらの手順に従ってダウンロードしてください:https://www.shapenet.org/。ShapeNetCoreはShapeNetデータセットのサブセットです。PyTorch3Dでは、バージョン1(57カテゴリ)とバージョン2(55カテゴリ)の両方をサポートしています。

次に、以下の`SHAPENET_PATH`を、ShapeNetCoreデータセットフォルダのローカルパスに変更してください。

In [ ]
# Setup
if torch.cuda.is_available():
    device = torch.device("cuda:0")
    torch.cuda.set_device(device)
else:
    device = torch.device("cpu")
    
SHAPENET_PATH = ""
shapenet_dataset = ShapeNetCore(SHAPENET_PATH)

R2N2データセットは、こちらの手順に従ってダウンロードできます:http://3d-r2n2.stanford.edu/。`ShapeNetRendering`と`ShapeNetVox32`のリンクを確認してください。R2N2データセットには、ShapeNetCore v.1データセットのサブセットである13カテゴリが含まれています。R2N2データセットには、各オブジェクトの独自の24個のレンダリングとボクセル化されたモデルも含まれています。

次に、以下の`R2N2_PATH`と`SPLITS_PATH`を、それぞれローカルのR2N2データセットフォルダパスと分割ファイルパスに変更してください。ここでは、R2N2の`train`分割を読み込み、各モデルのボクセルを返すようにします。

In [ ]
R2N2_PATH = ""
SPLITS_PATH = "None"
r2n2_dataset = R2N2("train", SHAPENET_PATH, R2N2_PATH, SPLITS_PATH, return_voxels=True)

読み込んだデータセットにインデックスを付けることで、モデルを取得できます。ShapeNetCoreとR2N2の両方で、このモデルが属するカテゴリ(synset IDの形、ImageNetのAPIで説明されているwnidと同等:http://image-net.org/download-API)、モデルID、頂点、面を調べることができます。

In [ ]
shapenet_model = shapenet_dataset[6]
print("This model belongs to the category " + shapenet_model["synset_id"] + ".")
print("This model has model id " + shapenet_model["model_id"] + ".")
model_verts, model_faces = shapenet_model["verts"], shapenet_model["faces"]

頂点と面を使用して、バッチ処理されたメッシュを操作するためのPyTorch3Dデータ構造である`Meshes`オブジェクトを作成できます。

In [ ]
model_textures = TexturesVertex(verts_features=torch.ones_like(model_verts, device=device)[None])
shapenet_model_mesh = Meshes(
    verts=[model_verts.to(device)],   
    faces=[model_faces.to(device)],
    textures=model_textures
)

R2N2では、R2N2の元のレンダリングをさらに調べることができます。たとえば、R2N2データセットの11番目のオブジェクトの2番目と3番目のビューを確認したい場合は、次のようにします。

In [ ]
r2n2_renderings = r2n2_dataset[10,[1,2]]
image_grid(r2n2_renderings.numpy(), rows=1, cols=2, rgb=True)

2. `torch.utils.data.DataLoader`を使用したデータセット¶

深層学習モデルのトレーニングでは、通常、バッチ単位の入力が必要です。PyTorchの`torch.utils.data.DataLoader`は、これを行うのに役立ちます。PyTorch3Dは、入力メッシュを単一の`Meshes`オブジェクト(バッチを表す)にグループ化する関数`collate_batched_meshes`を提供します。`Meshes`データ構造は、深層学習モデルの一部である可能性のある他のPyTorch3D演算子(例:`graph_conv`)によって直接使用できます。

R2N2の場合、バッチ内のすべてのモデルが同じ数のビューを持っている場合、ビュー、回転行列、平行移動行列、固有行列、ボクセルもバッチ処理されたテンソルにスタックされます。

**注記**:R2N2の`val`分割内のすべてのモデルは24個のビューを持っていますが、24個のビューを`train`と`test`分割に分割する8個のモデルがあり、その場合、`collate_batched_meshes`は行列、ビュー、ボクセルをリストとして結合することしかできません。ただし、`return_all_views = False`を設定することで、モデルの1つのビューのみを読み込むことで、これを回避できます。

In [ ]
batch_size = 12
r2n2_single_view = R2N2("train", SHAPENET_PATH, R2N2_PATH, SPLITS_PATH, return_all_views=False, return_voxels=True)
r2n2_loader = DataLoader(r2n2_single_view, batch_size=batch_size, collate_fn=collate_batched_meshes)

バッチ内のすべてのビュー(モデルごとに1つ)を視覚化してみましょう。

In [ ]
it = iter(r2n2_loader)
r2n2_batch = next(it)
batch_renderings = r2n2_batch["images"] # (N, V, H, W, 3), and in this case V is 1.
image_grid(batch_renderings.squeeze().numpy(), rows=3, cols=4, rgb=True)

3. PyTorch3Dの微分可能なレンダラーを使用したShapeNetCoreモデルのレンダリング¶

`ShapeNetCore`と`R2N2`のデータローダーには、PyTorch3Dの微分可能なレンダラー実装を使用して、モデルID、カテゴリ、またはインデックスを指定することでモデルのレンダリングをサポートするカスタマイズされた`render`関数が含まれています。

In [ ]
# Rendering settings.
R, T = look_at_view_transform(1.0, 1.0, 90)
cameras = OpenGLPerspectiveCameras(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],device=device)

まず、モデルIDで3つのモデルをレンダリングしてみます。

In [ ]
images_by_model_ids = shapenet_dataset.render(
    model_ids=[
        "13394ca47c89f91525a3aaf903a41c90",
        "14755c2ee8e693aba508f621166382b0",
        "156c4207af6d2c8f1fdc97905708b8ea",
    ],
    device=device,
    cameras=cameras,
    raster_settings=raster_settings,
    lights=lights,
)
image_grid(images_by_model_ids.cpu().numpy(), rows=1, cols=3, rgb=True)

データセットの最初の3つのモデルをレンダリングしたい場合は、インデックスでモデルをレンダリングできます。

In [ ]
images_by_idxs = shapenet_dataset.render(
    idxs=list(range(3)),
    device=device,
    cameras=cameras,
    raster_settings=raster_settings,
    lights=lights,
)
image_grid(images_by_idxs.cpu().numpy(), rows=1, cols=3, rgb=True)

あるいは、特定のモデルには興味がなく、特定のカテゴリからランダムなモデルを見たい場合は、`categories`と`sample_nums`を指定して行うことができます。たとえば、「蛇口」カテゴリから2つのモデル、「椅子」カテゴリから3つのモデルをレンダリングしたい場合は、次のようにします。

In [ ]
images_by_categories = shapenet_dataset.render(
    categories=["faucet", "chair"],
    sample_nums=[2, 3],
    device=device,
    cameras=cameras,
    raster_settings=raster_settings,
    lights=lights,
)
image_grid(images_by_categories.cpu().numpy(), rows=1, cols=5, rgb=True)

特定のカテゴリには興味がなく、データセット全体からランダムなモデルをレンダリングしたい場合は、`sample_nums`でレンダリングするモデルの数を設定し、`categories`を指定しないようにします。

In [ ]
random_model_images = shapenet_dataset.render(
    sample_nums=[3],
    device=device,
    cameras=cameras,
    raster_settings=raster_settings,
    lights=lights,
)
image_grid(random_model_images.cpu().numpy(), rows=1, cols=5, rgb=True)

4. データセット内の元のレンダリングと同じ向きでR2N2モデルをレンダリングする¶

上記のShapeNetCoreモデルと同じ方法でR2N2モデルをレンダリングできます。さらに、データセット内の元のレンダリングと同じ向きでR2N2モデルをレンダリングすることもできます。これには、R2N2のカスタマイズされた`render`関数と、`BlenderCamera`と呼ばれる別のタイプのPyTorch3Dカメラを使用します。

この例では、元のレンダリングと同じ向きで7番目のモデルをレンダリングします。まず、結果と比較するためにR2N2の元のレンダリングを取得します。

In [ ]
original_rendering = r2n2_dataset[6,[1,2]]["images"]
image_grid(original_rendering.numpy(), rows=1, cols=2, rgb=True)

次に、PyTorch3Dのレンダリングを視覚化します。

In [ ]
r2n2_oriented_images = r2n2_dataset.render(
    idxs=[6],
    view_idxs=[1,2],
    device=device,
    raster_settings=raster_settings,
    lights=lights,
)
image_grid(r2n2_oriented_images.cpu().numpy(), rows=1, cols=2, rgb=True)

5. R2N2モデルのボクセルの視覚化¶

R2N2データローダーは、モデルのボクセルも返します。R2N2の`render_vox_to_mesh`関数を使用して、それらを視覚化できます。これにより、ボクセルが`Meshes`オブジェクトに立方体化され、レンダリングされます。

この例では、元のレンダリングと同じ向きで、データセットの10番目のモデルを視覚化します。まず、結果と比較するためにR2N2の元のレンダリングを取得します。

In [ ]
r2n2_model = r2n2_dataset[9,[1,2]]
original_rendering = r2n2_model["images"]
image_grid(original_rendering.numpy(), rows=1, cols=2, rgb=True)

次に、ボクセルを`render_vox_to_mesh`に渡します。

In [ ]
vox_render = render_cubified_voxels(r2n2_model["voxels"], device=device)
image_grid(vox_render.cpu().numpy(), rows=1, cols=2, rgb=True)
pytorch3d
Facebook Open Source
Copyright © 2024 Meta Platforms, Inc
法務情報:プライバシー利用規約