multinerf - Mip-NeRF 360、Ref-NeRF、RawNeRF のコードリリース

(A Code Release for Mip-NeRF 360, Ref-NeRF, and RawNeRF)

Created at: 2022-07-23 06:47:15
Language: Python
License: Apache-2.0

MultiNeRF: Mip-NeRF 360、Ref-NeRF、RawNeRF のコードリリース

これは公式にサポートされている Google 製品ではありません。

このリポジトリには、3 つの CVPR 2022 論文 ( Mip-NeRF 360Ref-NeRF、および RawNeRF ) のコード リリースが含まれています。このコードベースは、Ref-NeRF と RawNeRF の内部実装を mip-NeRF 360 実装に統合することによって作成されました。そのため、このコードベースは mip-NeRF 360 に示されている結果を正確に再現する必要がありますが、Ref-NeRF または RawNeRF の結果を再現する場合はわずかに異なる場合があります。

この実装はJAXで書かれており、 mip-NeRFのフォークです。これは研究コードであり、それに応じて処理する必要があります。

設定

# Clone the repo.
git clone https://github.com/google-research/multinerf.git
cd multinerf

# Make a conda environment.
conda create --name multinerf python=3.9
conda activate multinerf

# Prepare pip.
conda install pip
pip install --upgrade pip

# Install requirements.
pip install -r requirements.txt

# Manually install rmbrualla's `pycolmap` (don't use pip's! It's different).
git clone https://github.com/rmbrualla/pycolmap.git ./internal/pycolmap

# Confirm that all the unit tests pass.
./scripts/run_all_unit_tests.sh

GPU または TPU をサポートするには、おそらく JAX インストールを更新する必要があります。

ランニング

トレーニング、評価、およびレンダリングのサンプル スクリプトは、 にあります

scripts/
。データセットが配置されている場所を指すようにパスを変更する必要があります。私たちのモデルといくつかのアブレーションのGin構成ファイルは にあります
configs/
。データセットの 1 つで各シーンのテスト セットを評価した後
scripts/generate_tables.ipynb
、論文の表で使用されたものと同じ形式で、すべてのシーンにわたるエラー メトリックを生成するために使用できます。

OOM エラー

Config.batch_size
メモリ不足エラーを回避するために、バッチ サイズ ( ) を減らす必要がある場合があります。これを行うが、品質を維持したい場合は、必ずトレーニングの反復回数を増やし、バッチ サイズを減らす倍率だけ学習率を減らしてください。

独自のデータを使用する

まとめ: まず、ポーズを計算します。次に、MultiNeRF をトレーニングします。3 番目に、トレーニング済みの NeRF モデルから結果のビデオをレンダリングします。

  1. ポーズの計算 (COLMAP を使用):
DATA_DIR=my_dataset_dir
bash scripts/local_colmap_and_resize.sh ${DATA_DIR}
  1. MultiNeRF のトレーニング:
python -m train \
  --gin_configs=configs/360.gin \
  --gin_bindings="Config.data_dir = '${DATA_DIR}'" \
  --gin_bindings="Config.checkpoint_dir = '${DATA_DIR}/checkpoints'" \
  --logtostderr
  1. MultiNeRF のレンダリング:
python -m render \
  --gin_configs=configs/360.gin \
  --gin_bindings="Config.data_dir = '${DATA_DIR}'" \
  --gin_bindings="Config.checkpoint_dir = '${DATA_DIR}/checkpoints'" \
  --gin_bindings="Config.render_dir = '${DATA_DIR}/render'" \
  --gin_bindings="Config.render_path = True" \
  --gin_bindings="Config.render_path_frames = 480" \
  --gin_bindings="Config.render_video_fps = 60" \
  --logtostderr

出力ビデオがディレクトリに存在するはず

my_dataset_dir/render/
です。

COLMAP を使用してポーズを計算する方法、または独自のデータセット ローダーを作成する方法の詳細については、以下を参照してください (SLAM や RealityCapture などの別のソースからのポーズ データが既にある場合)。

COLMAP を実行してカメラ ポーズを取得する

自分でキャプチャしたシーンの画像に対して MultiNeRF を実行するには、まずCOLMAPを実行してカメラの姿勢を計算する必要があります。これは、提供されているスクリプトを使用して実行できます

scripts/local_colmap_and_resize.sh
。ディレクトリ
my_dataset_dir/
を作成し、入力画像をフォルダー
my_dataset_dir/images/
にコピーしてから、次を実行します。

bash scripts/local_colmap_and_resize.sh my_dataset_dir

これにより、COLMAP が実行され、画像の 2x、4x、および 8x ダウンサンプル バージョンが作成されます。

Config.factor = 4
これらの低解像度の画像は、たとえばgin フラグを設定することにより、NeRF で使用できます。

デフォルトで

local_colmap_and_resize.sh
は、 は OPENCV カメラ モデルを使用します。これは、k1、k2 ラジアルおよび t1、t2 タンジェンシャル歪み係数を持つ遠近ピンホール カメラです。OPENCV_FISHEYE などの別の COLMAP カメラ モデルに切り替えるには、次のコマンドを実行します。

bash scripts/local_colmap_and_resize.sh my_dataset_dir OPENCV_FISHEYE

約 500 を超える画像を大量にキャプチャする場合は、COLMAP で網羅的マッチャーからボキャブラリ ツリー マッチャーに切り替えることをお勧めします (コメントアウトされた例については、スクリプトを参照してください)。

このスクリプトは、COLMAP のシン ラッパーにすぎません。COLMAP を自分で実行したことがある場合は、シーンを NeRF にロードするために必要なことは、シーンが次の形式であることを確認することだけです。

my_dataset_dir/images/    <--- all input images
my_dataset_dir/sparse/0/  <--- COLMAP sparse reconstruction files (cameras, images, points)

カスタム データローダーの作成

独自のデータのポーズが既にある場合は、独自のカスタム データローダーを作成することをお勧めします。

MultiNeRF にはさまざまなデータローダーが含まれており、そのすべてが基本の Dataset クラスから継承されています。

このクラスの役割は、ディスクからすべてのイメージとポーズ情報をロードし、NeRF モデルのトレーニングまたはレンダリング用にレイ データとカラー データのバッチを作成することです。

_load_renderings
継承されたすべてのサブクラスは、メソッド (デコレータによって抽象としてマークされている) を実装することによって、ディスクから画像とカメラ ポーズをロードする責任があり
@abc.abstractmethod
ます。次に、このデータを使用して、NeRF モデルにフィードするためのレイ + カラー データのトレーニング バッチとテスト バッチを生成します。光線パラメータは で計算され
_make_ray_batch
ます。

既存のデータ ローダー

例から作業するために、既に実装したさまざまなデータローダーに対してこの関数がどのようにオーバーロードされているかを確認できます。

私たちが依存している主なデータ ローダーは LLFF (歴史的な理由から名付けられました) で、これは COLMAP によって作成されたデータセットのローダーです。

実装による独自のローダーの作成
_load_renderings

新しいデータセットを作成するには、継承するクラスを作成し、メソッド

Dataset
をオーバーロードし ます。
_load_renderings

class MyNewDataset(Dataset):
  def _load_renderings(self, config):
    ...

この関数では、次のパブリック属性を設定する必要があります。

  • 画像
  • カムトワールド
  • ピクトカム
  • 高さ、幅

データセット ローダーの多くは他の有用な属性も設定しますが、これらは光線を生成するための重要な属性です。で光線を作成するために (ピクセル座標のバッチと共に) それらがどのように使用されるかを確認できます

camera_utils.pixels_to_rays

画像

images
= [N, 高さ, 幅, 3] RGB 画像の numpy 配列。現在、すべての画像が同じ解像度である必要があります。

外部カメラ ポーズ

camtoworlds
= [N, 3, 4] 外部ポーズ行列のnumpy配列。
camtoworlds[i]
実行できるように、カメラから世界への形式にする必要があります

pose = camtoworlds[i]
x_world = pose[:3, :3] @ x_camera + pose[:3, 3:4]

3D カメラ空間ポイント

x_camera
をワールド空間ポイントに変換し
x_world
ます。

これらの行列は、カメラの回転のOpenGL座標系の規則で格納する必要があります。x 軸は右、y 軸は上、z 軸はカメラの焦点軸に沿って後方です。

最も一般的な規則は次のとおりです。

  • [right, up, backwards]
    : OpenGL、NeRF、ほとんどのグラフィック コード。
  • [right, down, forwards]
    : OpenCV、COLMAP、ほとんどのコンピューター ビジョン コード。

幸いなことに、OpenCV/COLMAP から NeRF への切り替えは 簡単です。OpenCV ポーズ行列を で右乗算するだけ

np.diag([1, -1, -1, 1])
で、y 軸 (下から上) と z 軸 (前から後) の符号が反転します。 :

camtoworlds_opengl = camtoworlds_opencv @ np.diag([1, -1, -1, 1])

また、デフォルトの mipnerf360 構成ファイルを使用して最高のパフォーマンスを得るために、カメラ ポーズの変換をスケーリングして、それらがすべてキューブ内に収まるようにすることもできます。

[-1, 1]^3

入力ポーズの平行移​​動/回転/スケーリング変換を計算する便利なヘルパー関数を提供します。

camera_utils.transform_poses_pca
これは、ワールド空間の xy 平面を (PCA に基づいて) 地面に合わせ、すべての入力ポーズ位置が 内に収まるようにシーンをスケーリングします
[-1, 1]^3
。(この関数は、LLFF データ ローダーで mip-NeRF 360 シーンをロードするときにデフォルトで適用されます。) この変換が適用されたシーンでは、
camera_utils.generate_ellipse_path
ビデオをレンダリングするための適切な楕円形のカメラ パスを生成するために使用できます。

固有のカメラ ポーズ

pixtocams
= [N, 3, 4] 逆固有行列の numpy 配列、または [3, 4] 1 つの共有逆固有行列の numpy 配列。これらは OpenCV形式である必要があります。

camtopix = np.array([
  [focal,     0,  width/2],
  [    0, focal, height/2],
  [    0,     0,        1],
])
pixtocam = np.linalg.inv(camtopix)

焦点距離と画像サイズが与えられた場合 (中心に主点があると仮定すると、この行列は を使用して作成できます

camera_utils.get_pixtocam

camera_utils.intrinsic_matrix
または、結果の行列を使用して反転することによって作成することもできます 。

解像度

height
= int、画像の高さ。

width
= int、画像の幅。

歪みパラメータ (オプション)

distortion_params
= dict、カメラ レンズ歪みモデル パラメータ。このディクショナリは、文字列 -> 浮動小数点数からマッピングする必要があり、許可されるキーは
['k1', 'k2', 'k3', 'k4', 'p1', 'p2']
(最大 4 つの半径係数と最大 2 つの接線係数​​) です。デフォルトでは、これは空のディクショナリ
{}
に設定されています。この場合、歪み補正は実行されません。

Dataset の内部動作の詳細

パブリック インターフェイスは、標準の機械学習パイプライン データセット プロバイダーの動作を模倣しており、バッチの読み込み/作成方法や並列化方法の詳細を公開することなく、無限のデータ バッチをトレーニング/テスト パイプラインに提供できます。したがって、イニシャライザは、 を使用したディスクからのデータのロードを含むすべてのセットアップを実行し

_load_renderings
、親の start() メソッドを使用してスレッドを開始します。初期化子が戻った後、呼び出し元はすぐにデータのバッチを要求できます。

内部

self._queue
は として初期化されるため、要素が 3 つになると呼び出し時
queue.Queue(3)
に無限ループ
run()
がブロックされます。
self._queue.put(self._next_fn())
メイン スレッドのトレーニング ジョブは、キューの先頭から一度に 1 つの要素をポップするループで実行されます。データセット スレッドの
run()
ループは、キューに 3 つの要素を入力し、バッチが削除されるまで待機して、最後にもう 1 つプッシュします。

これは、メイン スレッドのトレーニング ループが完了するまで (通常は数十万回の反復) 無限に繰り返されます。その後、メイン スレッドは終了し、データセット スレッドはデーモンであるため、自動的に強制終了されます。

引用

このソフトウェア パッケージを使用する場合は、作成した構成論文を引用するか、このコードベース全体を次のように自由に引用してください。

@misc{multinerf2022,
      title={MultiNeRF: A Code Release for Mip-NeRF 360, Ref-NeRF, and RawNeRF},
      author={Ben Mildenhall and Dor Verbin and Pratul P. Srinivasan and Peter Hedman and Ricardo Martin-Brualla and Jonathan T. Barron},
      year={2022},
}