SfMで作成された巨大な点群の鳥瞰視点画像を作成する

車載のセンサーの観測情報つかってSfMをおこない環境地図を作成することがある。 この環境地図はかなり大きいサイズになり、点群は専用のViewerが必要になるため、他の人に気軽に共有して見てもらうみたいなことができないのが面倒だと思っている。 ここでは点群を俯瞰した状態を画像として作成し、その画像を他の人に共有することで解決できないかを考えた。

まず巨大な点群を描画するためのViewerはPotree, Open3D, pptkなどいくつか候補がある。 この中でOpen3Dが活発に開発されているので良いと考えた。pptkも良いのだが機能が最小限であり先々考えると不安がある。PotreeはOpen3Dを試して十分だと感じたので調べていない。

また、細かい要件だが、以下のようなことも求める

  • 要件①点群の3次元の座標と得られた鳥瞰視点画像の画素の座標をあとから対応付けできること
  • 要件②出力される鳥瞰視点画像が高解像度であること

これをOpen3Dで実現する方法を検討したところ、以下のことがわかった

  • 要件①はスクリーンショットを実行するとViewerの仮想カメラパラメタが一緒に出力さられるので満たすことができる。
  • 要件②はHeadlessレンダリングを有効にすると実現できる。

スクリーンショットを行うと以下のような名前のPNGJSONが保存される。

ScreenCapture_2023-03-21-12-25-37.png
ScreenCamera_2023-03-21-12-25-37.json

PNGスクリーンショット自体で、JSONは仮想カメラの外部パラメタと内部パラメタが記録されている。 これがあれば画素の座標をそれに対応する点群の座標に変換することが可能である。(地面の高さの情報は別途必要、もしくは一緒に取得可能なDepthを用いる)

ここで実装例として以下の記事で紹介されているドローンから空撮して作成された点群を扱う。
How to visualise massive 3D point clouds in Python | Towards Data Science

通常モードの場合はスクリーンショットを取ったり、点群の表示サイズを変えるのはキーボードのキーが割当たられていて、必要なキーを押下するだけでよいのだが、 ヘッドレスレンダリングの場合は画面が表示されないのでPythonから設定の変更と表示操作を行う必要がある。 そこが少し苦労したが、実装方法がわかったのでスクリプトを公開する。

gist.github.com

このスクリプトを実行すると以下のスクリーンショットが得られる。

ortho.png

$ file ortho.png 
ortho.png: PNG image data, 3000 x 3000, 8-bit/color RGB, non-interlace

サイズは3000x3000のPNGファイル 拡大するとわかるが、結構細部まで描画されている。 また、オルソ画像を作りたいのだが、現状はバグによりできない。詳細はコメントを参照のこと。 ヘッドレスレンダリングを有効にするための方法もコメントをい参照してほしい。

Open3DのVisualizerは他にもいくつか便利な機能を持っているので、使いこなすと色々できそうなので、また試したら記事にしようと思う。