iPhoneのLiDARを使って撮影したデータはどのようにして3Dデータに変換されるのかっていう雑記

## 3Dスキャンアプリの使い方はわかるけど、内部の仕組みが解説された記事はなかなかない

まず、僕はiOSのエンジニアではないので、前提知識が足りていない部分があると思うのですが、それを抜きにしてもLiDARデータから3Dデータを作り出す過程が日本語で説明された記事ってほとんどないなぁと思いましたので、とにかく調べまくったことをまとめていきます。

基本的には「自分用メモ」です。

## Scaniverseはどうやっているのか考察

iPhoneで利用できるようになったLiDARのデータを利用して3Dモデルを作成する「Scaniverse」というアプリがあリます。
使い方などはこちらが参考になると思います。
[Scaniverseを使ってスマホで3Dスキャンをしよう！](https://note.com/iwamah1/n/nc8a5427157ef)

こちらはざっくりこのようなことができます

- **スキャンする範囲は0.5~5mまでで選べる**
    - そもそもiPhoneは5m先までLiDARを利用したスキャンができる
- **位置情報も付与できる**
- **データをスキャンした後に、LiDARを利用するか、Photogrammetryするか選べる**
- **作成した3Dデータはメッシュとしてobjやglbなど、点群データとしてlasやplyなど主要形式で出力できる**

サクッとスキャンするだけで3Dデータが作成され、いろんな形式で出力できるのでとても便利ですね。

が、ここでいくつか疑問が湧いてきました。

- そもそも**どうやって3Dメッシュを作っている**の？
- LiDARモード利用を選択しても、**色付き点群が吐き出される**のはなぜ？
    - LiDARで得られるのはただの（というと語弊があるが）距離データ、つまり点群データであり、色の情報は持っていないはずなのになぜRGBが…？
- Photogrammetryモードを選択すると、Photogrammetryで点群を作成するんだろうけど、**Scaniverseはスキャン後にモードを選択する（LiDARと同じ工程でスキャンする）ので、いつ写真を撮っているんだろうか**？
    - スキャン時にLiDARに加えて動画（or 写真）を撮っているのかな？
- **LiDARモードでもobjなどのテクスチャ（色）付きモデルが作成できるのはなんで？**
  - うまいこと写真を貼っているんだろうか？

などなど疑問点は尽きませんね。

なので、一個ずつ調べて考察してみました。

## そもそもどうやって3Dメッシュを作っているのか

Appleが公式に出している記事でこんなものがありました。
[Visualizing and Interacting with a Reconstructed Scene](https://developer.apple.com/documentation/arkit/content_anchors/visualizing_and_interacting_with_a_reconstructed_scene)

これによると、**「ARKitはLiDARスキャナーを使用して物理環境のポリゴンモデルを作成します」**との記載があります。
ということでサクッと解決しました。やっぱり困ったときは公式ドキュメントですね。
つまり、**メッシュ自体はLiDARのデータを利用して、作成**することができます。
ポイントのデータから適切にエッジを繋いで、そこにサーフェスを貼ることでメッシュを作っているんですね。

ちなみに、LiDARからはこんなデータが取得できるようで、**リアルタイムに点群を表示させたり**することができるようです。
[Displaying a Point Cloud Using Scene Depth](https://developer.apple.com/documentation/arkit/environmental_analysis/displaying_a_point_cloud_using_scene_depth)

Qiitaにも、点群をリアルタイムにボクセル化して表示するっていう面白いことをしている方がいました。
[LiDARスキャナを使って現実世界をボクセルにしてみた](https://qiita.com/TokyoYoshida/items/1c62c01093e6a9be442e)

iOSのAPIを利用して手動で**LiDARのデータからOBJを作成**しようとする方も当然いて、ARMeshGeometryからMDLMeshってのに変換してそれができればOBJには簡単に変換できるとかなんとか…
[ARKit – How to export OBJ from iPhone/iPad with LiDAR?](https://stackoverflow.com/questions/61063571/arkit-how-to-export-obj-from-iphone-ipad-with-lidar)
[【iOS】ARKitのFace Trackingの結果をobjファイルとして出力する](https://iganin.hatenablog.com/entry/2021/12/18/214028)

ちなみに、Scaniverseではモードが選択できるようですが、軽量化オプションが存在し、そちらでは**「メッシュ化する前に、適切に点群を間引き（ここがめちゃむずい）、その後メッシュ化することで見た目の影響を抑えつつ出力される3Dデータを軽量化し、なおかつメッシュ化する前に点群を間引いていることで頂点数を抑えることができるのでデータ作成処理も早い」**といったことが書かれていますね。すごい。
[Mesh Simplification in Scaniverse](https://blog.scaniverse.com/mesh-simplification-in-scaniverse-981ca6564340)

## LiDARモード利用を選択しても、色付き点群が吐き出されるのはなぜ？

まず、そもそもiPhoneから取得できる**LiDARのデータは生データではない**らしいです。
[ARKit 4のLiDAR Depth API](https://qiita.com/shu223/items/722077b4bbe868f58ddc)

> The colored RGB image from the wide-angle camera and the depth ratings from the LiDAR scanner are fused together using advanced machine learning algorithms to create a dense depth map that is exposed through the API.
（広角カメラからのカラーRGB画像とLiDARスキャナからの深度定格が、高度な機械学習アルゴリズムを使用して融合され、APIを通じて公開される高密度の深度マップが作成されます。）

ということで、やっぱりScaniverse（に限らず）では**LiDARを利用したスキャン時にカメラの画像を利用し、点群にRGBをつけている**ようです。

当然、plyやlasで出力した時にはRGBを持っていました。

Photogrammetryを利用した際にはそもそも画像からしか作成できないので、**動画のフレームから画像を作り、それを利用している**んでしょう。
これで「Photogrammetryモード、いつ写真を撮っているんだろうか？」の疑問も解決しましたね。

## LiDARモードでもobjなどのテクスチャ（色）付きモデルが作成できるのはなんで？

スキャン時にカメラから得られるデータも利用していそうなことはわかりました。
で、こちらの記事では以下の手順でカメラからの画像を使ってテクスチャを貼っていそうなことが書いてあります。
[Texture ARMeshGeometry from ARKit Camera frame?](https://stackoverflow.com/questions/63733708/texture-armeshgeometry-from-arkit-camera-frame/71257170#71257170)

こちらでも似たようなことが書かれていますね。
[MetalWorldTextureScan](https://github.com/beatTheSystem42/MetalWorldTextureScan)

ということで、**テクスチャ自体はやっぱりカメラフレームから取得、生成**されていそうですね。

ではそのテクスチャはどうやって貼っているのでしょうか。

こちらでは**メッシュの頂点からテクスチャの座標を計算し、メッシュに適用してテクスチャを貼っている**ようなことが書いています。
[iPad Pro Lidar - Export Geometry & Texture](https://stackoverflow.com/questions/61538799/ipad-pro-lidar-export-geometry-texture)

## 結論

結果として、iPhoneで取得できるLiDARのデータからは以下の手順で3Dデータに変換されていそうなことがわかりました。
（詳しい方おりましたら、教えていただけると…）

- **LiDARデータスキャン時に、同時にカメラからのデータも利用し、色付け**
- **スキャン中にMetalでメッシュを生成**
- **テクスチャ作成のためにカメラフレームを保存**
- **スキャンしたデータの座標やメッシュからテクスチャ座標を計算し、テクスチャリング**