これは公式にサポートされている Google 製品ではありません。
このリポジトリには、3 つの CVPR 2022 論文 ( Mip-NeRF 360、 Ref-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、論文の表で使用されたものと同じ形式で、すべてのシーンにわたるエラー メトリックを生成するために使用できます。
Config.batch_sizeメモリ不足エラーを回避するために、バッチ サイズ ( ) を減らす必要がある場合があります。これを行うが、品質を維持したい場合は、必ずトレーニングの反復回数を増やし、バッチ サイズを減らす倍率だけ学習率を減らしてください。
まとめ: まず、ポーズを計算します。次に、MultiNeRF をトレーニングします。3 番目に、トレーニング済みの NeRF モデルから結果のビデオをレンダリングします。
DATA_DIR=my_dataset_dir bash scripts/local_colmap_and_resize.sh ${DATA_DIR}
python -m train \ --gin_configs=configs/360.gin \ --gin_bindings="Config.data_dir = '${DATA_DIR}'" \ --gin_bindings="Config.checkpoint_dir = '${DATA_DIR}/checkpoints'" \ --logtostderr
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 などの別のソースからのポーズ データが既にある場合)。
自分でキャプチャしたシーンの画像に対して 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 つの接線係数) です。デフォルトでは、これは空のディクショナリ
{}に設定されています。この場合、歪み補正は実行されません。
パブリック インターフェイスは、標準の機械学習パイプライン データセット プロバイダーの動作を模倣しており、バッチの読み込み/作成方法や並列化方法の詳細を公開することなく、無限のデータ バッチをトレーニング/テスト パイプラインに提供できます。したがって、イニシャライザは、 を使用したディスクからのデータのロードを含むすべてのセットアップを実行し
_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}, }