ふるお〜と!- FullAuto

AI・ロボットが普及しBI(ベーシックインカム)が早急に実現されることを願う元ニートのブログ

ふるお〜と!-FullAuto

PyTorch3Dのサンプルを動かすメモ

2D画像から3Dを生成、すなわち3D再構成に関するサンプルを動かすメモ。

pytorch3d/INSTALL.md at master · facebookresearch/pytorch3d · GitHub

を参考にインストールしてみる。

環境

OS:Ubuntu20.04
GPU:GTX1070

Prerequisite

Anaconda: Anaconda | Individual Edition

Install

$ conda create -n pytorch3d python=3.8
$ conda activate pytorch3d
(pytorch3d) $ conda install -c pytorch pytorch=1.7.1 torchvision cudatoolkit=10.2
(pytorch3d) $ conda install -c fvcore -c iopath -c conda-forge fvcore iopath

Nvidia CUBをインストールする。
CUBとは、CUDAプログラミングモデルのすべてのレイヤーに最先端の再利用可能なソフトウェアコンポーネントを提供するライブラリのこと。
conda環境なら、以下のコマンドだけでインストールできる。

(pytorch3d) $ conda install -c bottler nvidiacub

デモを動かすためのライブラリをインストール

(pytorch3d) $ conda install jupyter
(pytorch3d) $ pip install scikit-image matplotlib imageio plotly opencv-python

テストを動かすためのライブラリをインストール

(pytorch3d) $ pip install black 'isort<5' flake8 flake8-bugbear flake8-comprehensions

PyTorch3Dバイナリインストール

(pytorch3d) $ conda install pytorch3d -c pytorch3d

Example

以上のコマンドを実行すると

~/anaconda3/pkgs/pytorch3d-0.4.0-py38_cu102_pyt171/info/test/docs/examples

にexmapleが入っている。

(pytorch3d) $ python pulsar_basic.py

のようにすればExampleを実行できる。
チュートリアル

~/anaconda3/pkgs/pytorch3d-0.4.0-py38_cu102_pyt171/info/test/docs/tutorials

にある。
不親切にもipynbという形式で書かれているので、
そのままpythonコマンドを実行することができない。

したがって、一括で実行したい場合は新たにファイルを作り、In[]:をコピペしていくしかない。
jupyter nbconvertで.ipynbから.pyへ変換できる。

$ jupyter nbconvert --to python fit_textured_mesh.ipynb

Visual Studio CodeでJupyterをインストールして実行するのがナウいやり方。

python...で実行するとget_ipythonでエラーとなるため、 ipythonコマンドを使う。

$ python fit_textured_mesh.py

するとエラーになったので以下のファイルを修正 /anaconda3/envs/pytorch3d/lib/python3.8/site-packages/torch/
tensor.py

- 630:  return self.numpy()
+ 630:  return self.to("cpu").detach().numpy()

2つの要因でエラーになっていた。

各サンプルの要約

render_texrured_mesh 要約

テクスチャ付きのメッシュをレンダリングする このチュートリアルでは、以下の方法を紹介します。

.objファイルからメッシュとテクスチャを読み込む。 レンダラーの設定 メッシュのレンダリング 照明やカメラの位置などのレンダリング設定を変更する。 pytorch3d API のバッチ機能を使用して、メッシュを異なる視点からレンダリングする。

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

torch と torchvision がインストールされていることを確認します。pytorch3dがインストールされていない場合は、以下のセルを使ってインストールします。 Google Colabを使用している場合は、画像グリッドをプロットするためのutilsファイルを取得します。 または、ローカルで実行する場合は、以下のセルをアンコメントして実行します。

1. メッシュとテクスチャのファイルを読み込む

.objファイルとそれに関連する.mtlファイルを読み込み、Textures and Meshesオブジェクトを作成します。

Meshesは、PyTorch3Dで提供されている独自のデータ構造で、異なるサイズのメッシュのバッチを扱うためのものです。

TexturesUVは、メッシュの頂点UVとテクスチャマップを保存するための補助的なデータ構造です。

Meshesには、レンダリングパイプライン全体で使用されるいくつかのクラスメソッドがあります。

このノートブックをGoogle Colabで実行する場合、以下のセルを実行してメッシュのobjとテクスチャファイルを取得し、data/cow_meshというパスに保存します。ローカルで実行する場合は、データはすでに正しいパスに保存されています。

テクスチャーマップを可視化してみよう

PyTorch3Dには、テクスチャマップをmatplotlibで表示する方法が組み込まれており、頂点に対応するマップ上のポイントも表示されます。また、texturesuv_image_PILというメソッドがあり、同様の画像を取得してファイルに保存することができます。

2. レンダラーの作成

PyTorch3Dのレンダラーは、ラスタライザとシェーダで構成されており、それぞれがカメラ(正投影/遠近法)などのサブコンポーネントを持っています。ここでは、これらのコンポーネントの一部を初期化し、残りのコンポーネントにはデフォルト値を使用します。

この例では、まず透視カメラと点光源を使用し、フォンシェーディングを適用するレンダラーを作成します。その後、モジュール式のAPIを使って、さまざまなコンポーネントを変化させる方法を学びます。

3. メッシュをレンダリングする

光はオブジェクトの正面にあるので、明るく、画像にはスペキュラハイライトがあります。

4. ライトをオブジェクトの背後に移動させ、再レンダリングする

任意のキーワード引数をレンダラーへの呼び出しを通じてラスタライザ/シェーダに渡すことができるので、設定が変更されてもレンダラーを再初期化する必要はありません。

この場合、単純にライトの位置を更新し、それをレンダラーへの呼び出しに渡すことができます。

環境光のみで、鏡面ハイライトがないため、画像は暗くなりました。

5. オブジェクトを回転させたり、マテリアルのプロパティやライトのプロパティを変更する

その他、レンダリングパイプラインの様々な設定を変更することができます。ここでは

カメラの視野角の変更 ポイントライトの位置の変更 メッシュのマテリアルの反射率プロパティを変更

6. バッチ処理されたレンダリング

PyTorch3D APIでは、すべてのコンポーネントでバッチ入力をサポートすることを設計の中核としています。レンダラと関連コンポーネントは、バッチ入力を受け取り、1回のフォワードパスで出力画像のバッチをレンダリングすることができます。この機能を使って、メッシュを様々な視点からレンダリングしてみましょう。

7. Plotlyによる視覚化

メッシュを視覚化したいだけなら、微分可能なレンダラーを使う必要はありませんが、代わりにplotlyでメッシュのプロットをサポートしています。plot_meshesは、各Meshesオブジェクトのトレースを含むPlotly図を作成します。 バッチの場合は、plot_batch_individuallyを使うことで、自分でシーン辞書を構築することを避けることもできます。

また、両方の関数で軸の引数と軸の背景を変更することができます。

8. おわりに

このチュートリアルでは、objファイルからテクスチャ付きのメッシュを読み込み、MeshesというPyTorch3Dデータ構造を初期化し、ラスタライザとシェーダからなるレンダラを設定し、レンダリングパイプラインのいくつかのコンポーネントを変更する方法を学びました。また、MeshesをPlotlyのフィギュアにレンダリングする方法も学びました。

fit_textured_mesh要約

レンダリングでメッシュをフィットさせる このチュートリアルでは、以下の方法を紹介します。

.objファイルからメッシュとテクスチャを読み込みます。 テクスチャ付きのメッシュを複数の視点からレンダリングして,合成データセットを作成する. シルエットレンダリングの差分を使って,観測された合成画像にメッシュをフィットさせる 差分テクスチャ・レンダリングを用いて,メッシュとそのテクスチャを適合させる

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

torch と torchvision がインストールされていることを確認します。pytorch3dがインストールされていない場合は、以下のセルを使ってインストールします

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

または、ローカルで実行する場合は、以下のセルをアンコメントして実行します。

1. メッシュとテクスチャのファイルを読み込む

.objファイルとそれに関連する.mtlファイルを読み込み、Textures and Meshesオブジェクトを作成します。

Meshesは、PyTorch3Dで提供されている独自のデータ構造で、異なるサイズのメッシュのバッチを扱うためのものです。

TexturesVertexは、メッシュの頂点rgbテクスチャ情報を格納するための補助データ構造です。

Meshesには、レンダリングパイプライン全体で使用されるいくつかのクラスメソッドがあります。

Google Colabを使ってこのノートブックを実行する場合は、次のセルを実行してメッシュのobjファイルとテクスチャファイルを取得し、data/cow_meshというパスに保存します。ローカルで実行する場合は、データはすでに正しいパスに保存されています。

2. データセットの作成

様々なカメラポジションをサンプリングして、牛の複数の視点を表現します。テクスチャマップの補間を行うシェーダを備えたレンダラーを作成します。複数の視点から見た牛のメッシュにテクスチャを施した画像の合成データセットレンダリングします。

データセットの可視化:

このチュートリアルの後半では、レンダリングされたRGB画像と、牛のシルエットだけの画像にメッシュを当てはめていきます。後者の場合は、シルエット画像のデータセットレンダリングします。PyTorch3Dのほとんどのシェーダーは、RGBA画像の4番目のチャンネルとして、RGB画像と一緒にアルファチャンネルを出力します。アルファチャンネルは、各ピクセルがオブジェクトの前景に属する確率をエンコードします。このアルファチャンネルをレンダリングするために、ソフトシルエットシェーダを構築します。

3. シルエットレンダリングによるメッシュ予測

前節では、牛を複数の視点から撮影した画像のデータセットを作成しました。本節では、グランドトゥルースである牛のメッシュを知らない状態で、これらの対象画像を観察してメッシュを予測する。ここでは、カメラの位置と照明がわかっていることを前提とする。

まず、メッシュ予測の結果を可視化するために、いくつかのヘルパー関数を定義します。

球体メッシュから始めて,各最適化ステップにおいて,予測されたメッシュのシルエットがターゲットのシルエット画像により近いものになるように,各頂点のオフセットを学習します.まず、最初の球体メッシュを読み込みます。

予測されたメッシュのシルエットをレンダリングするために、新しい微分可能なレンダラーを作成します。

設定、損失、オプティマイザを初期化して、ターゲットのシルエットにメッシュを繰り返しフィットさせます。

最適化ループを書いて、球体メッシュから予測したメッシュをターゲット画像のシルエットに合うように繰り返し改良していきます。

3. テクスチャレンダリングによるメッシュとテクスチャの予測

予測されたレンダリングされたRGB画像とターゲット画像の比較に基づいて追加の損失を追加すると,メッシュとそのテクスチャの両方を予測することができます.前述のように,まず球体のメッシュを用意します.球体メッシュの各頂点の並進オフセットとRGBテクスチャカラーの両方を学習します。損失はシルエットだけでなくレンダリングされたRGBピクセル値に基づいているため、SoftSilhouetteShaderではなくSoftPhongShaderを使用します。

ここでは、設定、損失、およびメッシュをターゲットのRGB画像に反復的に適合させるために使用されるオプティマイザを初期化します。

最適化ループを書いて、球体メッシュから予測したメッシュとその頂点の色を、ターゲット画像にマッチするメッシュに繰り返し改良します。

予測された最終的なメッシュを保存します。

4. 予測した最終メッシュを保存

5. おわりに

このチュートリアルでは、objファイルからテクスチャ付きメッシュを読み込み、そのメッシュを複数の視点からレンダリングして合成データセットを作成する方法を学びました。また、レンダリングされたシルエットロスに基づいて、観測されたデータセットの画像にメッシュをフィットさせる最適化ループの設定方法を紹介しました。さらに,この最適化ループに,レンダリングされたRGB画像に基づく損失を追加することで,メッシュとそのテクスチャの両方を予測することができました.

fit_textured_volume

レイマーチングによるボリュームのフィット このチュートリアルでは、微分可能なボリュームレンダリングを使用して、シーンのビューのセットにボリュームをフィットさせる方法を説明します。

具体的には、以下の方法を説明します。

微分可能なボリューメトリックレンダラーを作成する。 ボリューメトリックモデルを作成する(Volumesクラスの使用方法を含む)。 微分可能なボリューメトリックレンダラーを使って、画像に基づいてボリュームをフィットさせる。 予測された体積を可視化する。

または、ローカルで動作させる場合は、次のセルをコメントアウトして実行します:a

1. シーンとマスクの画像を生成する

次のセルでは、トレーニングデータを生成します。このセルは、fit_textured_mesh.ipynb チュートリアルの牛のメッシュを複数の視点からレンダリングし、それを返します。

牛のメッシュのレンダラーによって生成された、画像とシルエットのテンソルのバッチ。 各レンダリングに対応するカメラのセット。 注意:ボリュームレンダリングの詳細を説明することを目的としたこのチュートリアルでは、generate_cow_renders関数で実装されているメッシュレンダリングがどのように動作するかは説明しません。メッシュレンダリングについての詳しい説明は、fit_textured_mesh.ipynb を参照してください。

  1. ボリューメトリックレンダラーの初期化 以下は、ターゲットイメージの各ピクセルからレイを放出し、レイに沿って一様に間隔を空けたポイントのセットをサンプリングするボリュームメトリックレンダラーを初期化します。各レイポイントでは、シーンのボリュームモデル(モデルは後のセルで説明され、インスタンス化されます)の対応する場所を照会することによって、対応する密度と色の値が得られます。

レンダラーは、レイマーチャーとレイサンプラーで構成されています。

レイサンプラーは、画像ピクセルから光線を放出し、それに沿ってポイントをサンプリングする役割を担っています。ここでは、標準的なPyTorch3Dの座標グリッド規則(右から左への+X、下から上への+Y、ユーザーから離れた位置への+Z)に従ったNDCGridRaysamplerを使用しています。 レイマーチャは、各レイに沿ってサンプリングされた密度と色を受け取り、各レイをレイのソースピクセルの色と不透明度の値にレンダリングします。ここでは、標準的な Emission-Absorption raymarching アルゴリズムを実装した EmissionAbsorptionRaymarcher を使用しています。

3. ボリューメトリックモデルの初期化

次に,シーンのボリュームモデルをインスタンス化します。このモデルでは、3D空間を立方体のボクセルに量子化します。各ボクセルは、ボクセルのRGBカラーを表す3Dベクトルと、ボクセルの不透明度を表す密度スカラーで記述されます([0-1]の範囲で、高いほど不透明です)。

密度と色の範囲が[0-1]であることを保証するために,体積の色と密度の両方を対数空間で表現しています。モデルのフォワード関数の間、対数空間の値はシグモイド関数に渡され、対数空間の値を正しい範囲にします。

さらに、VolumeModelにはレンダラーオブジェクトが含まれています。このオブジェクトは最適化の間、変更されることはありません。

このセルには,レンダリングされたカラーとマスクの間の不一致を計算するヒューバー損失関数も定義されています.

    1. ボリューメトリックモデルの初期化 次に、シーンのボリュームモデルをインスタンス化します。このモデルでは、3D空間を立方体のボクセルに量子化します。各ボクセルは、ボクセルのRGBカラーを表す3Dベクトルと、ボクセルの不透明度を表す密度スカラーで記述されます([0-1]の間の範囲で、高いほど不透明です)。

密度と色の範囲が[0-1]であることを保証するために,体積の色と密度の両方を対数空間で表現しています。モデルのフォワード関数の間、対数空間の値はシグモイド関数に渡され、対数空間の値を正しい範囲にします。

さらに、VolumeModelにはレンダラーオブジェクトが含まれています。このオブジェクトは最適化の間、変更されることはありません。

このセルには,レンダリングされたカラーとマスクの間の不一致を計算するヒューバー損失関数も定義されています.

4. ボリュームのフィット

ここでは、微分可能なレンダリングによるボリュームフィッティングを行う。

ボリュームをフィットさせるために、target_camerasの視点からレンダリングを行い、得られたレンダリング結果を観測されたtarget_imagesおよびtarget_silhouetteと比較する。

比較は、target_images/rendered_imagesおよびtarget_silhouettes/rendered_silhouettesの対応するペア間の平均huber(smooth-l1)エラーを評価することによって行われる。

5. 最適化されたボリュームの可視化

最後に、ボリュームのY軸を中心に回転する複数の視点からレンダリングすることで、最適化されたボリュームを可視化します。

6. まとめ

このチュートリアルでは、既知の視点からのボリュームのレンダリングが、各視点の観測画像と一致するように、シーンの3Dボリューム表現を最適化する方法を紹介しました。レンダリングは、NDCGridRaysamplerとEmissionAbsorptionRaymarcherで構成されたPyTorch3Dのボリューメトリックレンダラーを用いて行われました。