2019.12.25

線画のトレースを題材にしたAR機能の検証

こんにちは。F.S.です。
あと数年で一般化するかもしれないARグラス時代のユーザー体験をイメージしながらスマホAR(ARKit)の機能検証をしています。

ところで、最近うちの子が流行りのアニメのイラスト(模写)を描くようになりました。なんか学校で流行ってるみたいです。
熱心にやっているのでトレーシングペーパーを買ってやったりしたのですが、ARを使えばトレースが簡単かもという発想で今回はこれを題材にアプリを試作・検証してみます。

今回の試作アプリの動作環境はこちらの通りです。

  • iPhone XR
  • iOS 13.2.3, 13.3

試作アプリの利用イメージ

トレースしたい対象の絵または文字を写真に撮って、紙面の上に投影してトレースに使用します。
動画は画像マーカー(くまの画像)を利用した場合の様子です。


利用技術とその考察

オクルージョン効果

オクルージョンとは物体の背後に位置するCGを物体の背後に隠れるように描画する手法です。iOS13(ARKit3)からA12チップ以降を搭載したデバイス(iPhone XS, XR,11など)に限り、人物に対してオクルージョンができるようになりました。

試作アプリをオクルージョンの有無で比較してみます。

左があり、右がなしです。

手本画像は半透明にしているのでオクルージョンなしでも使えますが、オクルージョンなしでは手本が手前に浮いてるような錯覚があります。オクルージョンがあると手本が紙面に自然に乗っているように見えます。これだけ見るとオクルージョンの効果が高いように見えますが、実際にトレースする上では視点がペン先に集中するのでオクルージョンがあってもなくても影響はないように思えました。

手本の設置(空間トラッキング)手法

2種類のトラッキング手法で手本の設置を試しました。
  • ワールドトラッキング
    • 空間を認識して検出した平面の位置に手本を設置する
    • いわゆるマーカーレスAR
  • イメージトラッキング
    • 特定の画像を認識してその画像の位置に手本を設置する
    • いわゆるマーカーAR
まずはワールドトラッキングを試しました。次の動画は平面認識して手本を設置した場合の様子です。



ワールドトラッキングは手軽に手本を設置できる反面、描こうとすると手本の位置が安定せずブレてしまいます。カメラに映るのが特徴のない平面(紙面)と、動く物体(手先)になるので、空間認識するには厳しい環境ですね。

したがって、最終的に採用したのはイメージトラッキングです。マーカーとなるイメージを準備する煩わしさはありますが、冒頭の動画の通り手本位置は非常に安定しています。

ARオブジェクトを鑑賞ではなくトレース用途で使うには手本の安定が第一ですので、技術的には衰退感がありますが、イメージトラッキングの方が実用的です。

使用感

実際に子供にこれを使ってアニメキャラクターを描かせてみました。スマホスタンドを利用すると快適になります。


その姿は拡大鏡を使って細かな作業をする職人のようにも見えます。ハ◯キルーペ & ARとか意外と受けるかもしれません。


うちの子はそれほど絵心はないのですが、アニメキャラクターの模写ができてます。(それで楽しいのかどうかはさておき・・)

技術情報補足

利用技術については前述の通りですが、得られた知見をいくつか補足します。

オクルージョン

オクルージョンを使用するにはARセッションのコンフィグレーションで有効にするだけです。
let configuration = ARWorldTrackingConfiguration()
configuration.frameSemantics.insert(.personSegmentation)
これだけで標準のレンダラー(ARView, ARSCNView)では勝手にオクルージョンが効くようになります。今回の用途ではARオブジェクトは常に手の下に隠れてほしいので深度データを使用しないオプションを選択しています。

frameSemantics の種類は公式ドキュメントで参照できます。
https://developer.apple.com/documentation/arkit/arconfiguration/3089121-framesemantics

余談ですが、オクルージョンを有効にするとARFrame(ARSession の currentFrame)からセグメント(segmentationBuffer)と深度情報(estimatedDepthData)が得られます。


左からフレームのキャプチャ画像、セグメントバッファ、深度データです。実際のサイズはキャプチャ画像 1440×1920 px に対し、セグメントバッファ、深度データのサイズは192×256 px と低解像度です。

Metalで独自にレンダリングする際は ARMatteGenerator でバッファを補正して高解像度のセグメント・深度情報に復元するようです。

Appleの公式に ARMatteGenerator を使ったサンプルコードがあります。
https://developer.apple.com/documentation/arkit/effecting_people_occlusion_in_custom_renderers

イメージトラッキング

トラッキングするイメージをアプリのアセットに登録するのですが、イメージにはいくつか推奨事項があります。
  • ヒストグラムが偏ってない(明暗の偏りがない)画像
  • コントラストが高い(明暗がはっきりした)画像
  • 物理サイズが 1 × 1 インチ以上
  • 画像サイズが 480 × 480 px 以上
試しに特徴の少ない小さな画像を登録しようとすると、このように警告メッセージが表示されます。

ジェスチャー

UIGestureRecognizer で一般的なジェスチャーによる操作が簡単に追加できます。
  • パン(UIPanGestureRecognizer)で手本を設置面に沿って移動
  • ピンチ(UIPinchGestureRecognizer)で手本を拡大・縮小
  • ローテーション(UIRotationGestureRecognizer)で手本を回転
1点注意が必要なのは、パンジェスチャーによりオブジェクトを移動させる操作にて移動先のスクリーン座標から3D空間座標に変換する方法です。
基本的には3D空間への hitTest で座標を取得しますが、下記の通り使い分ける必要があります。
  • 空間認識で検出した平面等への hitTest は ARSCNView の hitTest
    func hitTest(_ point: CGPoint, 
           types: ARHitTestResult.ResultType) -> [ARHitTestResult]
    
  • 3DオブジェクトへのhitTest は 3DSCNSceneRenderer プロトコルの hitTest
    (ARSCNView が継承する SCNView が 3DSCNSceneRenderer プロトコルに準拠しています)
    func hitTest(_ point: CGPoint, 
         options: [SCNHitTestOption : Any]? = nil) -> [SCNHitTestResult]
    
平面認識してオブジェクトを設置する場合は前者でも問題ないのですが、イメージトラッキングでは空間認識しないので後者を使います。

筆者もそうですが、ARKitからSceneKitを始めた人は後者の存在に気づかず悩んでしまうかもしれません。公式ドキュメントにはちゃんと注意書きがあるんですけどね。
(引用)https://developer.apple.com/documentation/arkit/arscnview/2875544-hittest

なお、上記は SceneKit を利用する場合ですが、RealityKit を使う場合も同様にそれぞれの hitTest があるようです。

イメージフィルタ

これはAR体験に直接関係ないトピックですが、トレースする線がわかりやすくなるように手本画像を加工しています。
加工にはApple純正のCore Image(CIFilter)で対応しているフィルターを使います。

試作アプリで使用したフィルターを解説します。
イメージトラッキングのマーカーに使ったくまの画像をサンプルに使います。

元画像

CIToneCurve
線(色が濃い部分)を強調するために濃淡のバランスを調整します。ちょっとわかりにくいですが、塗りつぶしの部分が元画像よりも薄くなっています。

CIDotScreen
白黒の2値に変換します。濃淡はドットの密度で表現します。ドットの大きさはパラメータ指定します。漫画のスクリーントーンみたいになります。

CIColorInvert
次のフィルタでアルファチャンネルを作りたいため、事前に白黒を反転します。

CIMaskToAlpha
グレースケール画像をアルファチャンネルに変換します。元画像の黒い部分が透過になるアルファチャンネルが生成されます。生成される画像は、白一色の画像+アルファチャンネルになります。

CIColorCrossPolynomial
多項式のパラメータを指定してRBG値を変更します。紙面上で手本が視認しやすい青色に変換してます。

各フィルターの効果は公式ドキュメントを参照するとわかりやすいです。
https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html

なお、CIFilterは実機のGPUに最適化されているためか、デバッグを実機でなくシミュレータで実行すると期待する結果が得られないので注意が必要です。

おわりに

デジタル化が進む世の中、先進技術を使ってアナログな作業をするというなんとも言えない体験でしたが、現実世界と融合するxRの用途はそういうところにこそあるんだなぁと感じました。将来ARグラスになったら習字や図工の授業が楽になるのは間違いないです。

それではまた。

次世代システム研究室では、アプリケーション開発や設計を行うアーキテクトを募集しています。アプリケーション開発者の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ 募集職種一覧 からご応募をお願いします。

Pocket

関連記事