これちのPost-it

技術ネタをペラペラと

ARKit 2.0 で何が変わったのか Apple 公式ドキュメントから読み解いてみた

はじめに

ARKit 2.0 が発表されました。

いろいろな機能が追加されました。 まとめ記事を読んで何となく新機能の雰囲気は掴めたのですが、やはりエンジニアならば「どんなクラスが追加されたのか?」「どうやってそれが実現できてるのか?」といった部分が気になりますよね。

そんな時、やはり一番参考になるのは Apple の公式ドキュメントです。

自分の勉強も兼ねて、公式ドキュメントから ARKit を調査していきたいと思います。 (いろいろ書きますが公式ドキュメント上で分かることをまとめただけでアプリはまだ作っていません。そこをご理解ください)

参考リンク

ARKit | Apple Developer Documentation

上のリンクにある Topics をざーっと眺めつつ、「Beta」の表記がついているものがおそらく ARKit 2.0 にて追加された機能でしょう。そこをメインに調査します。

あとは自分の過去記事も参考になるかもしれません。 (約1年前の記事ですが) korechipostit.hatenablog.com

ARKit アプリの作成方法もこちらにまとめてあります。(こちらも約1年前の記事ですが) korechipostit.hatenablog.com

ARSession

バイスカメラや自己位置推定のために必要となるモーション情報を扱うクラスです。 Shared object なので通常は1つのインスタンスのみ存在します(多分)。

しかしこのクラスのインスタンスだけでは AR は実現しません。 ARSession の構成を決めるために必要となるのが ARConfiguration クラスです。

これは AR Session の構成のために必要となる基底抽象クラスなので、実際のアプリでは ARConfiguration クラスを継承した具象クラスのインスタンスを必ず使う必要があります。 その具象クラスが以下の4つです。

2つ目の AROrientationTrackingConfiguration クラスはおそらくあまり使われることがないため今回説明しませんが、気になった方はリンクを辿ってください。

イメージしやすいようにここは実際のコードを見てみましょう。

XCode で Augmented Reality App を作成すると ViewController.swift が作られます。

  • ViewController.swift
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // Create a session configuration
        let configuration = ARWorldTrackingConfiguration()

        // Run the view's session
        sceneView.session.run(configuration)
    }

viewWillAppear() の中で ARWorldTrackingConfigurationインスタンスが作成され、session.run() の引数に渡されていますね。

せっかくなので ARWorldTrackingConfiguration クラスも少し覗いてみます。(コメントは一部外してます)

@available(iOS 11.0, *)
open class ARWorldTrackingConfiguration : ARConfiguration {

    @available(iOS 11.3, *)
    open var isAutoFocusEnabled: Bool

    open var planeDetection: ARWorldTrackingConfiguration.PlaneDetection

    @available(iOS 11.3, *)
    open var detectionImages: Set<ARReferenceImage>?
    
    public init()
}

オートフォーカスの設定、平面検知の設定、検知する画像の設定を行うことができそうです。

以前調査した時(約1年前)は ARConfiguration クラスを継承したクラスは 6DOF 自由度で位置・向きが取れる ARWorldTrackingConfiguration と 3DOF 自由度で向きのみがとれる AROrientationTrackingConfiguration しかありませんでした。

今はさらに2つが追加されています。(ARFaceTrackingConfiguration は以前からあったかも?) それぞれについて詳しくみていきましょう。

ARImageTrackingConfiguration

背面カメラ画像から、特定のイメージ(軸となる画像)を検出して追跡する方式です。 ARImageTrackingConfiguration を使うと、ARKit はバイスの動きを使用せず、既知の 2D 画像の動きをトラッキングすることでのみ3D 空間を推定します。 既知のイメージを検出したら、6DOF 自由度でデバイスの動きを推定し始めます。

逆に言ってしまえば軸となる画像がカメラ映像内に存在しない場合はデバイスの位置・向きが推定できないため AR オブジェクトが配置できないということです。

ただし ARImageTrackingConfiguration モードだけ画像が検出できるというわけでもなく、ARWorldTrackingConfiguration でも画像検出はできるようです。 両者の違いとしては、

メリット デメリット
ARWorldTrackingConfiguration 既知の画像がなくても AR が続行可能 計算量が多いためあまり多くの画像が一度に検出できない
ARImageTrackingConfiguration より多くの画像が一度に検出可能。また、モーションセンサーを使用しないため動いている場所(電車内など)でも AR オブジェクトが配置できる。 既知の 2D 画像がカメラに写っている間しか AR オブジェクトが配置できない

基本的には ARWorldTrackingConfiguration+ 画像検出の方が検出したい画像が多くない場合は使い勝手良さそうですが、移動中にも使用したいならば ARImageTrackingConfiguration もアリだと思います。

電車内でも使えるというのはなかなか助かる場面もあるでしょう。 (とはいえ軸となる画像が常に見えていないとなので、ユースケースは限られそうな印象ではある)

それでは ARImageTrackingConfiguration モードにて使用する画像を設定する方法です。 まずその検出したい画像を ARReferenceImage と呼びます。手順は

  1. ARReferenceImage オブジェクトをランタイムもしくは Xcode asset catalog にて定義
  2. trackingImages プロパティにイメージを設定
  3. configuration をセッションの run(_:options:) メソッドにパス
    • ここは ARWorldTrackingConfiguration と同様

結構簡単にできそうでうね。 Xcode asset catalog の使い方はここを参考にしましょう。Apple 公式の説明です。

ARFaceTrackingConfiguration

フロントカメラの映像を使ってフェイストラッキングをすることができます。 映像内に顔を検知したら `ARFaceAnchor オブジェクトが追加されます。

そのアンカーには顔の位置・向き・ 顔のトポロジ・表情の情報が含まれます。 これらの情報を使って顔の周りに何かのオブジェクトを配置することができます。

f:id:korechi:20180608083319p:plain

ARWorldTrackingConfiguration

6DOF 自由度でデバイスの位置・向きを推定するモード。 こちらは以前からあったのですが、一部新機能があったのでまとめておきます。

  • planeDetection
    • 現実世界の水平・垂直(ARKit 1.5 より追加)平面を検出し ARPlaneAnchor オブジェクトとしてセッションに追加
      • デフォルトでは水平・垂直平面検知はオフ
      • 有効にすると、平面を検知した際に ARPlaneAnchor オブジェクトをセッションに追加し、ARSessionDelegate オブジェクトを介してアクセスが可能
  • detectionImages
    • 既知の 2D 画像を認識し動きを追跡し ARImageAnchor オブジェクトとしてセッションに追加
      • ARReferenceImage クラスを使って検知させたい画像を設定可能(XCode の Asset Catalog を使う)
      • 位置・向きを検知
    • 静的な画像が望ましい(画像検知は連続的には行われない)
    • iOS 12.0 以降では maximumNumberOfTrackedImages を設定することで連続的に画像検知が行われ、動的な画像検知が可能になる
    • パフォーマンス的には25枚以上の画像は使わない方が良いが、検知したい画像をタイミングで切り替えることで総合枚数を増やすことができる
    • セッションに影響を与えずに別の画像をセットしたい場合はセッションの run(_:options:) メソッドを呼べば実現可能
  • detectionObjects
    • iOS12 より追加
    • 3D オブジェクトを認識し ARObjectAnchor オブジェクトをシーンに追加
    • 3D オブジェクトの作成には現実世界でそれをスキャンし、ARWorldMap を使って [ARReferenceObject] インスタンスを生成
      • それらはファイルとパッケージとして保存されるため、ARKit アプリの中で使える& XCode の asset catalog でも使える

ARWorldMap

空間マッピングの状態を保持します。現実世界の情報だけでなく ARAnchor オブジェクト(平面や追加したオブジェクト)も含まれます。 なかなかこれは強烈な機能ですね。Project Tango のようにシーンの保存・ロードが可能になるようです。

また、保存したワールドマップを他の人と共有することで複数人で AR シーンの共有が可能にもなります。 加えて、AR アプリを中断した後もワールドマップをロードすることで以前の状態を復元することが可能です。 ARK 2.0 の目玉はここにあると言っても過言ではないでしょう。 この機能は以下の関数を使うことで実現されます。

簡単に使えそうですね。 この記事を書き終えたらさっそく試してみたいと思います。

AREnvironmentProbeAnchor

こちらも ARKit 2.0 から追加されたクラスです。

特定のエリアに対して環境光情報を提供するオブジェクトを提供します。

環境テクスチャと呼ばれる、3D アセットレンダリングにおいて物体の表面に光の反射を再現するのに必要となる情報の元となるテクスチャを AR シーン内に配置することで AR オブジェクトに画像ベースの光反射感を再現させます。

ARKit はセッション中にカメラ映像から環境テキスチャを生成することができます。

これを実現するためには environmentTexturing プロパティを設定します。値は以下の2つが設定可能です。

  • ARWorldTrackingConfiguration.EnvironmentTexturing.manual
    • AREnvironmentProbeAnchor をセッション内のどこかに自分で配置してシーン内で環境テクスチャを適用したい場所を設定するモード
  • ARWorldTrackingConfiguration.EnvironmentTexturing.automatic
    • 自動でよしなに環境テクスチャを設定してくれるモード

ただ、どちらのモードにせよ ARKit は自動的にカメラ映像を収集し環境テキスチャを生成してくれるようです(すごい)。

生成された環境テキスチャは、デリゲートメソッド session(_:didUpdate:) で見つけたオブジェクトのenvironmentTexture プロパティでアクセスできます。

簡単に書いていますがかなりすごいです。 この機能に関しては HoloLens すら超えていると言えますね。早く使ってみたい。

3D オブジェクトの検知

現実世界で認識された 3D オブジェクトは ARReferenceObject として保持されます。

3D オブジェクトを検知した時のトリガーを使用することで、例えば美術館で特定の彫刻を認識した時にそれの説明文を表示する、といったことが実現可能になります。 これも ARKit 2.0 から追加された機能で、今回の目玉機能であると言えるでしょう。

この機能を使うためにはまず検知するための 3D オブジェクトを一度作成する必要があります。

そのためには、

  1. ARObjectScanningConfiguration で ARSession を実行
  2. 様々なアングルから認識したいオブジェクトの周りを見て情報を収集
  3. セッション内で認識したいポジションを決定し、createReferenceObject(transform:center:extent:completionHandler:) メソッドを呼ぶ
  4. export(to:previewImage:) メソッドを呼び 3D オブジェクトを保存
    • .arobject ファイルとして保存されます

そうして作成された 3D オブジェクトを検知するためには、セッションコンフィグの detectionObjects プロパティにセットします。

一度作られた .arobject ファイルは、Xcode asset catalog を使うことで別のアプリに組み込むことも可能です。

おわり

ざっとこんなところです! ふわっとした ARKit 2.0 の新機能が少しでもしっくりくるものになれば幸いです。

ただし、まだ実際にアプリを作ってはいないのでこれから作っていこうと思います!

追記

Unity から ARKit 2.0 の ARWorldMap のサンプルアプリを実機動作させた記事を書きました。参考になれば

korechipostit.hatenablog.com