🐈

iOSエンジニアがARにキャッチアップしたときに勉強したこと

2020/12/24に公開

大人の事情でARアプリをつくらなくいけなくなって、何も知らん状態からキャッチアップしたときに勉強したことをまとめていきます。

AR開発、何を使う?

AR開発で、大手が開発してるライブラリは下記があります。

Unity: ARFoundation
Apple: ARKit
Google: ARCore

僕は流れでARFoundationを使うことになりましたが、他の選択肢もあったかもしれません。
ARFoundationはARKit/ARCoreと互換性があり、Unityで開発したものをiOS/Android環境で動かすことができます。
サンプルアプリがUnity公式で公開されているので、お手軽に試す[1]ことができます。

https://github.com/Unity-Technologies/arfoundation-samples

ARは日進月歩で進化しているジャンルなので、ライブラリも変化が速いです。
とはいえ、それなりに成熟している感じもあって、上で紹介した3ライブラリで、「このライブラリではできるけど、これだとまだできない」みたいなのはそんなないなって感じました。

機能の比較表を見ると、大きな違いはなく見えます。
ARKitも「できる!」ってなってるけど、実際はハードウェアの制約あるやつ何個かある気がします。
(というか他社に遅れるのはテック企業として致命的なので、死ぬ気でキャッチアップしてるんでしょうね)

ARの基礎

やや乱暴な説明になりますが、ARというのは、

現実のカメラ映像
+
2D/3Dオブジェクト

で表現する技術です。
(ここから現実のカメラ映像を抜いて、完全に2D/3Dオブジェクトだけで構成するとVRというジャンルになると思います)

単にオブジェクトを重ねるという話であれば、完全に別のレイヤーをつくって重ねれば実現できます。
(実際スマホのカメラアプリは既にカメラ映像の上にソフトウェアのボタン乗ってますし)
ただそういう話じゃなく、「あたかも現実世界の一部のようにオブジェクトを表示する」のがAR技術のキモです。
これが長年非常に難しかったのです。

以下、僕が知らなかったAR用語を具体的に紹介しながら、2020年現在ARライブラリでできることをフワッと把握してもらえたらと思います。
なお用語の解説は僕なりの解釈であり、必ずしも正確ではないです。

Depth

Depth: 深度。ARの文脈で使う場合、画像データの各ポイントに対する奥行きを表す情報のこと。

カメラの中に映っている物体との距離は測れるでしょうか?
通常はNOですね。

けれど現在のスマホにはそれができる機種があります。
それが、深度センサーがついている端末です。


引用元: Depth in Depth #iOSDC

Depthがわかれば物体との距離が高精度で推定できますし、↑のスライドで紹介されているように、背景を判定するという使い方もできます。
また距離だけではなく、Depthで物体表面の凹凸も検出できます。
人の顔の凹凸を読みとって、それに合ったテクスチャーをつくる、みたいな使い方もできそうです。

この前なんかのネット記事で、もしスマホの深度センサーの技術が進みすぎると、
たとえば道を歩いている女性のスリーサイズをスマホかざした瞬間に取得する、みたいな犯罪(犯罪でもないのか?)に使う用途もあって危ない、という主張も見ました。
今の段階でそこまで心配するのは心配しすぎじゃないかとは思いますが、確かに技術的には可能かもしれませんね。

Raycast

Raycast: レイキャスト。無理やり和訳すれば光線放射。物体との距離を検知する。衝突判定に使える

じゃあDepthってどうやって取得するの? って話なのですが、そこで出てくるのがこのRaycast。
レーザー光を放射して、その戻る時間を検知することで、Depthを検知できます。

LiDAR

LiDAR: Light Detecting and Rangingの略。深度センサーのすごいやつ

Apple製品だとiPad Pro第四世代, iPhone 12 Pro」, iPhone 12 Pro Maxに搭載されて、話題になりました。
Raycastを行うセンサーです。

名前的にどこかの企業の商標なのかと思ってましたが、一般用語みたいです。
レーダーと同じ扱いみたい。
レーダーは電波を使うけれど、LiDARは光を使う、とのこと。

スマホやタブレットだと何使ったらいいか分かりませんが、LiDARの応用分野でもっとも成功しているのは自動運転技術だそうです。
従来の技術と比較して、屋外に強い・暗所に強いという特徴を持っているLiDARですが、小型化が難しかったらしいんですが、いまやiPhoneに搭載されたのはすごいですね。

ちなみに、自動車の自動操縦で使われるようなLiDARは1km先でも検出できるようなレベルですが、iPhoneに搭載されているのは5m程度とのことです。

Occlusion

Occlusion: オクルージョン。物体の前後関係によって、本来物理的に見えないはずの物体が見えないようになっていること。ARの世界だと必ずしも当たり前ではない。

今回僕の開発したアプリだと納得いく結果にならなかったんですが、たとえば表示したいオブジェクトをカメラ映像の3m奥に配置したとしましょう。
もしその間に別の(リアルの)物体をおけば、当然その物体でオブジェクトは隠れますよね?

けれどこれを実現するためには実はかなり大変です。
現実世界の物体との推定距離を取得して、空間のXYZ座標のZ座標を計算、そのZ値とオブジェクトのZ値を比較して、前後関係を切り替えないといけません。

2020年現在、ARライブラリを使うと、Occlusionは室内なら結構実現できてるんですが、室外に出ると厳しいです。
Depth取得の仕組み上、屋外だとARアプリ上手くいかないケースは多いですね。

PlaneDetection

PlaneDetection: 平面検知

ARアプリをつくる上で、地面がどこかは大きな問題です。
けれど映像を解析して、地面がどこか判定するのは結構大変です。
人間の目だとすぐわかりますが、機械に判定させようとすると難しいです。

なんか簡単にできそうで、やらせてみると意外と難しいことの一つかもしれませんね。

これに関してはARライブラリが軒並み対応しており、ライブラリにお任せすればできる機能かと思います。

LightEstimation

LightEstimation: 光源検知

ARアプリでやろうとしている内容によっては、明るさがクリティカルになってくることもあるかと思います。
そんなときは光源検知をしてやると、現実世界の明るさが取れます。
僕が開発しているアプリはあまり気にせずにすみましたが、ちゃんとやると大変そうですね。

PeopleOcculusion

PeopleOcculusion: ピープルオクルージョン。人間を検知したら何らかの前後関係をつける

Occulusion自体いい訳がないのに、PeopleOcculusionとなると本当にどう訳したらいいかわからないですね。。。
人間を検知したらとにかくオブジェクトの前に配置したい、とか、そういうやつです。

Collision Detection

Collision Detection: 衝突判定

これは必ずしもAR限定ではなく、ゲームでもオブジェクト同士の衝突をどう判定するか、という問題があります。
ARでは更に現実の物体とオブジェクトの衝突判定が入ります。

これが適切にできてないと、一気に非現実感が増してしまうポイントでもあります。
けれど、僕が開発する中だと正直あまり考えませんでしたね……

AR世界と現実世界の座標系

AR開発の当初よく混乱したんですが、スマホのカメラを構えた地点が原点となって、座標系が構築されます。
イメージ図はこんな感じです。

IMG_67C3399B83B4-1.jpeg

Y値を増やすと高くなって、Z値を増やすと遠くなります。

Unity上のScale(1, 1, 1)は、現実世界の1m^3なので、めちゃくちゃデカいです。
開発初期はよくオブジェクトが表示されなくて困っていましたが、大きすぎると表示されません。
(素人考えで、10m^3の四角形を表示したら、クソデカオブジェクトでカメラがいっぱいになるのを想定していましたが、自分が四角の中にいると見做されるのかダメでした)

脚注
  1. もし平易な解説が欲しければAR Foundation 4.0 入門この辺りがいいかと ↩︎

Discussion