Blog
PFN2024 夏季インターンに参加させていただいた、東京大学 情報理工学系研究科 創造情報学専攻修士 1 年の 渡辺 羽亜人 と申します。大学ではコンピュータ・グラフィックスの研究室に所属しており、複数の画像から3Dビューを再構築する手法の一つである3D Gausssian Splattingの表現力を向上させる研究をしています。
この度、プロジェクトインターンとして、4D Gaussian SplattingをWebブラウザで見るためのViewerの開発に取り組みました。現在の専門が3Dであることと、個人開発や他企業でのアルバイトでWeb開発をしていた経験から今回のプロジェクトのインターンとして参加させていただけることになりました。本ブログでは、今回のインターンでの成果物についてご紹介させていただきます。
本プロジェクトにおけるモチベーション
3D Gaussian Splattingとは
複数の画像から対象物体の3D Sceneを再構成するための技術であり、3D Gaussian distributionで表現されるGaussianの集合で物体の表面を近似します。既存の手法と比較して、最適化にかかる時間が短く、再構築後の3D Sceneも高品質であるという特徴があります。
4D Gaussian Splattingとは
Image from Spacetime Gaussian Feature Splatting for Real-Time Dynamic View Synthesis
3D Gaussian Splattingに対して時系列を拡張した技術であり、Gaussianの位置、透明度、角度等を動かすことにより動きのある3D Sceneを再構成することができます。再構成後のSceneではカメラの位置と角度を視聴者自身が自由に動かして、任意のカメラアングル映像を見ることができます。
PFNでは4D Scanサービスを提供しており、内部では4D Gaussian Splattingを使用しています。
Web Viewer
4D Gaussian Splattingをデモで見せるにはViewerが必要になりますが、UnityなどのNative AppよりもWebアプリとして作成した方が、PCとモバイルデバイス両方に対応でき、環境ごとのビルドの問題も発生しないため、より広く使っていただくことができます。 しかしながら、4D Gaussian Splattingの安定したWeb Viewerは公開されておらず、存在するOSSは最大数秒程度のファイルしか実行できないという問題がありました。
そこで、本プロジェクトでは任意の長さの4D Gaussian Splattingを再生でき、4D Scanチームでの運用に向いたUIを備えたWeb Viewerを開発することになりました。
4D Gaussian Splatting Web Viewerについて
以下が、作成したWeb Viewerになります。
UI
一時停止、再開ボタン、現在の時間と全体の時間の表示、シークバーはYouTubeに近いUIを採用しました。これにより、新規ユーザーでも直感的な操作を行うことが可能になります。
カメラの位置の操作はマウスやトラックパッドを用いて行います。以下の操作を用意しています。
- 軌道移動(PCとモバイル両方)
- 中心座標にカメラの視線を向けたまま、軌道周りを動く操作です。
- OSSである3D Gaussian Splatting Web Viewer を参考にしました。
- ポインティング
- 軌道移動の中心座標を変更する操作です。
- クリックした位置に中心座標を変更します。
- 並行移動
- 前後(PCとモバイル両方)
- 上下左右(PCのみ)
- カメラの回転(左右)(PCのみ)
4D Gaussian Splattingのデータ構造
用意した4D Gaussian Splattingは 1 file 1/3秒分のデータを保持しているため、1秒間に3回データを切り替える必要がありました。
また、Gaussian Splattingは3D Viewの再構築に大量のGaussianを用いるため、データサイズが大きいといった特徴があります。実験に用いたデータを例に挙げると、上記の人一人分のデータで150K個程度のGaussianがあり、20秒で約180MBでした。iOSのブラウザの1タブあたりのヒープ領域は501MBに制限されていることを踏まえると、重いデータであることが分かります。そのため、極力Gaussianのデータをヒープ領域でコピーしないような設計にすることがポイントになります。
処理の流れ
上記の図が、ビューワーに必要な処理の流れになります。
- 全Gaussianのデータをヒープ領域に読み込む
- Gaussianをカメラの視線方向にソートする
- Gaussianデータをレンダリングする
2,3は毎フレーム繰り返し実行する必要があり、特に2のソートはカメラの位置が変わったタイミングで必ず行います。
システムデザイン
上記が設計したシステムになります。大まかに以下の3つの部分に分けられます。
- Frame function
- フレーム更新毎に実行される関数です。
- 表示するGaussianが保持されているファイルとファイル内における時間のオフセットを算出し、shaderに渡すデータ(texture)を作成します。
- Sorting worker
- Gaussianのソートを行うスレッドです。
- Frame functionにより呼び出されます。
- 大量のGaussianのソートを行うため、Frame functionとは別のスレッドで実行されます。
- WebGL shader
- Gaussian Splattingのレンダリングを行います。
- 並列に実行するためにshaderで実行しました。
- Gaussianのデータは数が多いため、uniform変数ではなくtextureとして受け取っています。
APIデザイン
Playerのロジックを保持するGs4dPlayerクラスを作成し、Reactコードから分離しました。イベントリスナやUI自体の実装はReactに入れ、カメラや再生に関する操作はGs4dPlayerのメソッドを呼び出すことで、レンダリング結果に影響を与えます。 このような構成にすることでフロントエンドの要件が代わり、別のフレームワークを使用する場合でも切り替えやすくなりました。
ポインティング UI
軌道移動UIではあらかじめ設定されているの中心位置の周りをカメラが移動します。しかしながら、中心位置を任意の場所に設定し直せると使い勝手が良いです。そこで、上図のようにクリックした場所にカメラから仮想的な光線を飛ばし、Gaussianに衝突した位置に中心位置を設定し直す機能を作成しました。
実装の詳細
- ベース: OSSであるSplatvをベースに開発を行いました。
- 言語: TypeScript
- Graphics API: WebGL + GLSL ES 3.0
- Graphics ライブラリ: Three.js
- ベクトルや行列の演算に使用しました。
- Development server: Vite
- フロントエンドフレームワーク: React, MUI
- ReactのStrict Modeで実装することで、安全な設計に近づけることができました。
- ボタンやシークバーはMUIのものを使用しました。
パフォーマンス
Mac(M2 Pro)(Chrome)とiPhone15 Pro(Safari)で実験を行いました。データは 1 ファイル約3MBのデータを使用しました。 Macでは40秒のデータで50-60FPS, 10秒のデータで110-120FPS、 iOSでは10秒のデータで50-60FPSでした。iOSにはヒープ領域の制限がありましたが、10秒分は再生できることが確認できました。
(単位はFPS)
Macにおいて、データの長さにより、FPSが変化している理由はソート時に必要なファイルだけでなく、全ファイルのソートを行なっており、ファイル数が増えるに連れて処理が重くなることが大きな原因であると考えられます。
この問題は後述するストリーミング処理を導入することで軽減されると思われます。
Motion Sequence
連続した時系列の画像を並べて配置したものはMotion Sequenceと呼ばれ、スポーツで選手の動きの遷移を可視化するためなどに使用されます。
Motion Sequenceを4D Gaussian Splattingで実現する機能をWeb Viewerに追加しました。
本機能は作成時、既存のどのViewerにも実装されていませんでした。 4D Gaussinan Splattingで行うと、物体の動きの遷移を横に並べたものを、どの方向からでも見ることができるため、スポーツや教育への応用が期待されます。
操作方法
- 「+」ボタンを押すことで、押した時点での固定されたオブジェクトが複製されます。
- 自動的に元のオブジェクトと一定の間隔を空けて配置されます。
- 「ALLIGN」ボタンを押すとカメラの横方向に複製されたデータを並べます。
- 「RESET」ボタンを押すと複製されたデータが全て削除されます。
Motion Sequenceのシステムデザイン
Motion Sequenceを実装するためにシステムデザインにおける①の部分を拡張しました。Motion Sequenceでは複数のオブジェクトのGaussianをレンダリングする必要があります。ShaderにはGaussianのデータを1つに統合(1つのtextureに)して渡す必要があるため、データのマージ処理を追加しています。また、オブジェクトはカメラに対して手前にあるものからレンダリングする必要があるため、各オブジェクトの中心位置を用いてソートを行なってからマージをしています。
Future Work
インターン期間は2ヶ月弱と限られた時間であったため、まだ荒削りな部分も多いです。実用に近づけるために必要な機能の代表として以下が挙げられます。
Streaming
現状のシステムでは初期化時に全てのGaussianのファイルをメモリ上にロードしていますが、ファイル数が多くなった場合、初期化に時間がかかってしまい、直近では使用しないデータもメモリに載ったままになってしまうという問題があります。そこで、ストリーミングを導入し、必要なデータを必要なタイミング(または少し前のタイミング)でメモリ上にロードし、再生が終わったファイルはメモリから破棄する仕組みとすることで、より長い時間のデータを再生できるようになります。
本インターンを通して
苦労したこと
- ベースに採用したOSSがJavaScriptで 1 ファイルに全てが書かれており、分かりやすい形に書き直すのが大変でした。
- 特に、カメラ操作周りの計算が分かりにくかったので自分で計算を定義し直し、新しい操作を追加するのに時間がかかりました。
- ShaderにGaussianのデータを渡すときは、texture(画像ファイル)として渡す必要があり、自分でデータの順序を決めてtextureファイルを作る必要がありました。バグが発生するとtextureデータの数値を吐き出して調査をする必要があるのでデバッグに時間がかかりました。
学んだこと
メンターさんや、チームの方から多くのフィーバックを頂き、様々なことを学ばせていただきました。特に印象に残っていることとして以下が挙げられます。
- コードをレビューしていただき、Viewerをどのようにフロントエンドフレームワークから切り離すかなどの設計面について多くを学ばせていただきました。
- 他のライブラリの実装やAPIを積極的に見に行き、参考にするという姿勢も学ぶことができました。
- 実用にあたって、4Dチームからレビューもいただけたので、ソフトウェアのクオリティを考えるきっかけにもなりました。
自分で大きなコードを書くときに、管理が難しいと日頃から感じていたため、インターン期間中に学ばせていただいたことはとても有益であると感じています。
最後に
インターン中は技術的に初めて取り組むことも多く、スムーズに進まないこともありましたが、期間内で目標としていた成果を上げることができ、最終発表では様々な方に良い評価をいただけたことを嬉しく思っています。
全面的なサポートをしていただいた、メンターのAkitaさん、Matsuokaさんをはじめ、お忙しい中データを用意していただいたKobayashiさん、実用を踏まえた上で有益なフィードバックをくださったMatsumotoさん、そしてインターン期間中にお世話になった全ての方々に感謝申し上げます。
PFN Day miniやLT会、経営陣トークなど交流の場を設けていただき、会社の事業だけでなく、雰囲気も知ることができました。イベントの企画、準備をしていただいた方々にも感謝申し上げます。
2ヶ月弱お世話になりました。ありがとうございました!