ARKit を使ってアプリを作ったので、それに際し気にかけたことやノウハウを雑にまとめておく。

制作物概要

こちらの記事にある AR Photoplay というアプリを作った。

[iOS App] AR Photoplay — 写真を飾るかのように動画を飾ろう

簡単にいうと、

  1. 動画を撮って、実物の写真としてプリントする
    (写真を部屋に飾ったりしよう!)
  2. 写真にiPhoneをかざす
    ⇒ 写真が画像認識され、写真の位置に動画が再生される!

ってアプリ。
画像認識してそこに動画を表示する、という部分でARKitを利用している。

環境情報

  • XCode 10.2.1
  • Swift 5.0
  • ARKit 2.0
  • iOS 12.2

気にかけたこと

ARアプリを作る上で、もしくは ARKit で画像認識する際に気にかけた方が良さそうと思ったことや、自分の行った工夫などを書き連ねていく。

ユーザーとAR空間のインターフェース領域を広くとる

スマートフォン用のARといえば、カメラを使うことになる。
カメラプレビュー上にARコンテンツを合成表示することでARエクスペリエンスを提供する(この画面がユーザーとAR空間のインターフェースになる)。ここで没入感を邪魔しないためには、プレビュー画面を広く取り、障害物となるUIをなるべく表示しないことが大事になると思う。画面の上下にナビゲーションバーやツールバーなどを表示していると、それだけで画面が狭くなったり、視界が遮られたりしてしまい、没入感が下がってしまう。

私の作成した AR Photoplay のアプリでは AR用の画面上からなるべくUIを減らせるように考慮してアプリ全体の画面と遷移を設計している。AR用の画面上に唯一ナビゲーションバーを表示しているが、無色透明の背景に白色の文字にすることでなるべくARエクスペリエンスの邪魔にならないよう工夫した。

↓がその画面のスクショ。左上に「< Favorites」 とあるのが前の画面に戻るためのUI。白文字が目立ち過ぎず、目立たなさ過ぎなず丁度良いと思う。

カメラの動きに対するARコンテンツの追従性能

ARKit でARコンテンツを表示するときは、次のどちらかを利用することになる:

以下の違いがある (使用感については実際に自分で試している):

  • ARWorldTrackingConfiguration
    • iOS 11.0+ の端末で利用可能 (ARKit 1.0 からの機能)。ただし画像認識の機能は iOS 11.3+ の端末で利用可能 (ARKit 1.5 からの機能)。
    • 現実世界をスキャンして平面を認識し、平面に紐づけてARコンテンツを配置するような、多くのARアプリで必要とされる用途に使える。また、認識した平面上から画像を認識して、そこに紐づけたARコンテンツ配置も可能 (画像認識は ARKit 1.5 からの機能)。
    • コンテンツがAR空間に一度配置されると、画面外になっても存在しつづける (画像認識機能だと違ったかも?試したんだけど忘れた)。リッチなARエクスペリエンスに向いている。
    • 画像検出の機能を使った場合は、検出位置・向きの更新が遅く、ARコンテンツの追従に明らかにラグが出る。0.5秒以下程度の間隔でコンテンツ表示位置がカメラ/検出画像の動きに追従するような感じ。iPhoneをゆっくり動かしただけでもはっきりとラグが感じらる。
  • ARImageTrackingConfiguration
    • iOS 12.0+ の端末で利用可能 (ARKit 2.0 からの機能)
    • 現実世界の平面認識はしておらず、画像認識・トラッキングして認識箇所に紐づけてARコンテンツを配置する。
    • 配置されたコンテンツは画面外になると存在しなくなる。
    • コンテンツ表示位置がリアルタイムに更新される。iPhoneを素早く動かしたとしてもラグはほとんど感じられない。

機能面では前者のARWorldTrackingConfigurationが優れているのだが、画像認識に限定すると性能面では後者のARImageTrackingConfigurationが優れている。

今回制作したアプリでは、機能的には画像認識があればよいので前者後者どちらでも可だが、性能的には後者が優れていることからARImageTrackingConfigurationを選択した。

ちなみに、デバイスのOSバージョンに応じて使い分けるといった手も可能だ; iOS 12.0 未満ならARWorldTrackingConfigurationを、iOS12.0 以上ならARImageTrackingConfigurationで対応できる。
しかし私は、使い勝手が悪いものをそもそも使わせたくなかったので、思い切って iOS 12.0+ のみを対象としてARWorldTrackingConfigurationのみの採用とした。

認識対象とする画像の物理サイズについて

ARKitで画像認識の機能を利用する場合、ARReferenceImage.physicalSize に、現実世界における認識対象の縦横の大きさを指定する必要がある。

この値は適当でも意外と大丈夫だが、実物との差があまりにも大きすぎると動画の表示が点滅するようになってしまった(認識がうまくいったり行かなかったりを短時間に繰り返す)。写真のサイズはある程度決まってるので(L版が最も一般的)、それに大体合わせた。壁一面を埋める程に大きなの写真だと上手くいかないかもしれないが、ほとんどのケースでは問題は起こらないだろう。
ユーザーに厳密な値を入力してもらうという手段をとれば、大小様々なサイズに対して安定して動作させられるのだが、それを入力させるのはユーザーにとって相当面倒だろうと思い、今回はphysicalSizeは固定値でで済ませた。

(この文章を書きながら今更気づいたが、先の固定値をデフォルト値としておいて、必要に応じてユーザーがphysicalSizeを設定できるようにするのが良さそうだ。)

余談: 物理サイズの推定

記事執筆時点では Beta 機能なのだが、iOS 13.0+ (ARKit 3.0 からの機能) ではARWorldTrackingConfigurationautomaticImageScaleEstimationEnabled プロパティによって画像の物理サイズを推定させることができ、大小様々な画像を安定して認識させられるようになりそう。
ただしARImageTrackingConfigurationには実装されない機能なので、私が AR Photoplay のアプリで使うことはなさそう。

認識対象とする画像の枚数について

ARKit のドキュメントによると、画像認識の正確さと性能を高く保つためには、約25枚以下の画像セットとするのが良いようだ。

Image detection accuracy and performance are reduced with larger numbers of detection images. For best results, use no more than around 25 images in this set.
(https://developer.apple.com/documentation/arkit/arworldtrackingconfiguration/2941063-detectionimages
より)

上記はARImageTrackingConfigurationのドキュメント中の記載だが、ARImageTrackingConfigurationの方ではこれについて触れられていなかった。
もしかしたら、ARImageTrackingConfigurationではこれより枚数を増やしても問題ないかもしれない。ARImageTrackingConfigurationの方が元々パフォーマンスが出やすいので、少なくとも性能の観点からは25枚以上で問題ないと言えるだろう。しかし、正確さの観点からはどうなんだろうか? わからない。

AR Photoplay のアプリにおいては、ユーザーが複数のアルバム(アプリ内ではポートフォリオと呼んでいる)を作成できるようにし、1アルバムごとに 24コンテンツ を保存できるようにした(アルバム内のコンテンツ数==認識画像数)。アルバムを切り替えると認識画像セットも切り替わる。
25 でなく 24 にしたのは、↓ の画像のようにUICollectionView で 3xN に表示した際にキリが良いから (3の倍数だから)。

画像認識に使えないエラー画像の扱い

ARKitでの画像認識に使えない画像が認識画像セットに含まれていた場合、ARセッションの実行中にランタイムエラーが発生し、ユーザーはAR機能が使えないか、最悪アプリがクラッシュする。この状況はなんとしても回避しなければならない。そのためにも、画像認識に使えない画像を検知する必要がある。

ある画像がARKitでの画像認識に使えるかどうか、というのを調べる方法は大きく2通りある:

  • assetとしてアプリにバンドルする場合: 使えない画像とその理由を Xcode が警告してくれる
  • 〃 しない場合(ユーザーが決める場合): プログラムでチェックしなければならない

AR Photoplay のアプリでは、ユーザーが保存した動画から最初の1フレームを画像化し、それを認識画像としている。
つまり、認識画像はユーザー依存なので、画像認識に使えるかどうかはプログラムでチェックしなければならない。

AR Photoplay のアプリでは、ARセッション実行時のランタイムエラーを拾い(アプリはクラッシュさせない)、エラー内容を解析して原因となっているコンテンツとエラーの理由を特定している。
その詳細な方法は以下の記事にまとめた。

ARKitでのイメージトラッキング/画像認識において Invalid Reference Image を特定する

エラーのあるコンテンツとその理由をユーザーに提示し、エラーを取り除くための対処を促すようにしている(↓画像)。

ポラロイドのような正方形の写真/動画

これは ARKit とは直接関係ない話だが、AR Photoplay は動画を撮影する機能を持っている。

AR Photoplay では、コンテンツを選択して写真を印刷する機能があるのだが(プリンターは別途必要)、普通の写真だけでなく正方形のポラロイド風のものもオシャレでいいなと思った。
というわけで、正方形の動画を撮影できるような機能を実装した。ついでに、縦横さまざまな長方形にも対応させた。

↓ のように、撮影するサイズを自由に選べるようになっている。

この動画のアスペクト比がそのまま認識画像のアスペクト比になるわけだが、ARKitにおける認識画像には3:1 以下の制約がある(?)。ただ、この制限は ARKit 1.0 のときのものと思われる。5:1 で試しても ARKit 2.0 ではエラーにならなかった。

あまりアスペクト比を大きくしすぎると 100px x 100px 以上 という認識画像の別の制約を満たさなくなることもあって、とりあえず 3:1 までにした。

余談

この撮影機能は単体でも使えそうだと思ったので、ライブラリ化した。CocoaPodsで使える。

[Swift] FlexibleAVCapture で 縦長/横長/正方形 など自由なサイズの動画を撮影する

このライブラリの利用例を示すため(と自分が使うため)に、オープンソースなアプリも作った。

[iOS App] Flex Camera で好きな形に iPhone の動画撮影を

おわり

カテゴリー: Tips

hahnah

はーな Webエンジニア。モバイルアプリも少々。Elmが好き。

0件のコメント

コメントを残す

メールアドレスが公開されることはありません。