WWDC2018で発表されたARKit2.0
WWDCでのビデオからの情報やAppleの公式Documentsに載っている情報を元に書いていきます。
追記
iOS12がリリースされたので、サンプルコードを作りました! 👇👇👇
サンプルコードを作ってわかったことを元に本記事も加筆訂正を加えています。
新しいARAnchor
AREnvironmentProbeAnchor, ARObjectAnchorはARkit2.0で追加された新しいAnchor。ARAnchorクラスを継承している。
今までARPlaneAnchor(ARKit1.0から), ARFaceAnchor(ARKit1.0からiPhoneXのみ), ARImageAnchor(ARKit1.5から)などがあったが、ARKit2.0で新たな2つが追加された。
Anchorと言えば、最近のARCore1.2におけるCloud Anchorが思い出される。
ARCoreのCloud AnchorsをSwift, iOSで試してみた
CloudAnchorを利用する際は、以下のようにGARAnchorのtransformからARAnchor
を生成していた。
func session(_ session: GARSession, didResolve anchor: GARAnchor) {
let arAnchor = ARAnchor(transform: anchor.transform)
sceneView.session.add(anchor: arAnchor)
}
空間をより一意に認識するために、このAnchorが欠かせない。
今回追加された2つに対する僕の理解は以下。
AREnvironmentProbeAnchor
An object that provides environmental lighting information for a specific area of space in a world-tracking AR session.
は直訳すると、特定環境におけるライティング情報。
こちらも今回から追加された、var environmentTexture: MTLTexture?
というpropertyがあって、Anchorに対するテキスチャ情報が取れる。
WWDC2018のWhat’s New in ARKit 2では、テーブルの上に現実のバナナを置いたときに、銀のバケットにバナナの様子を反射することができ、AR物体のりんごのバケットの環境をよりリアルに表現できるようになったと説明している。
銀のバケットにバナナの反射が写り込んでいるのがわかるであろうか?これがARKit1.xではできなかったこと。
engagetの記事の解説が分かりやすかったので以下に引用。
鏡や銀食器はもちろん、車のボディやスマホの画面、磁器に至るまで、およそ光沢のあるものには、すべて「周囲の風景や色」が反射している。この反射を物体に映し込む技術を「環境マッピング」という。ゲームでいえば、メタルマリオのテカり感や、グランツーリスモの車のボディのなまめかしさだが、ARKit 1までは環境マッピングに対応していなかったので、「現実にあるものをCGの物体に反射させる」ことができなかった。これだとどうしても「合成っぽさ」が残る。
しかしARKit 2ではカメラが捉えた現実の世界の状況から、反射のための「環境マップ」がリアルタイムに生成され、物体に反映される。この写真の場合、リンゴの入った金属の食器はCGであり、バナナは実際に机の上にあるものだ。ARKit 1ではバナナの黄色は反映されないが、ARKit 2では、ぼんやりとバナナが映り込んでいる。
https://japanese.engadget.com/2018/06/08/arkit2/
ARObjectAnchor
物体を勝手に認識してくれて、今までのPlaneAnchorなどと同じようにAnchorを付与してくれる。これはかなりデカイ。
ARKitとVisionを使って物体認識してそこに何かを貼り付けるというサンプルを作ったことがあるが、Visionで得られる物体情報は2DのboundingBoxだったので、そこの側面を座標まで得ることはできなかった。ARObjectAnchorのおかげでかなりそれがやりやすいはず。
ARObjectAnchorには、var referenceObject: ARReferenceObject
というプロパティがある(これもARKit2.0から)。次に続く。
スゴイ物体認識
物体をスキャン | それを認識 |
---|---|
ARReferenceObject
これがスゴイ。
center, extent, scaleというpropertyがあるので、物体を検出し、その位置や大きさなどを検出することができる。(現状事前にその物体のcenter, extent, scaleは作成時に手動で定義しておく必要がある)
これで、実際にある物体を加工したりすることができると思う。SnowやSnapChat, FacebookMessangerでFaceFilterができると思うが、これが物体に対してできるイメージ。
また、
init(archiveURL: URL)
というイニシャライザに注目したい。
ARReferenceObjectは .arobject
という拡張子のファイルとしてアウトプットすることができ、そしてそれはアプリで使うことができる。さらに、一度アウトプットすれば、そのファイルは他のアプリでもimportして使えて物体認識に利用することができる。
WWDC2018のWhat’s New in ARKit 2では、ネフェルティティの物体を認識して情報を保存し、後から再びみたときもネフェルティティが認識できた様子がデモされていた。
自分もデモアプリを使ってみたが、複数ある別の見た目のタンブラーの中から、正しいタンブラーをboundingBoxごと認識できた。
世界ごと保存!?
ARWorldMap
一度作った拡張現実情報を保存して、次にカメラを開いた時に、同じAnchorを探して、前回と同じような位置に仮想物体が出てくるように再現することができる。
ARSessionに用意された getCurrentWorldMap(completionHandler:)
メソッドを使って、その時のARWorldMap
が得られる。
これを以下のような感じでアーカイブできて、
func writeWorldMap(_ worldMap: ARWorldMap, to url: URL) throws {
let data = try NSKeyedArchiver.archivedData(withRootObject: worldMap, requiringSecureCoding: true)
try data.write(to: url)
}
以下のように、再現できる。
func loadWorldMap(from url: URL) {
let mapData = try Data(contentsOf: mapURL)
guard let worldMap = try? NSKeyedUnarchiver.unarchivedObject(of: ARWorldMap.classForKeyedUnarchiver(), from: mapData) as? ARWorldMap
else { throw ARError.invalidWorldMap }
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = .horizontal
configuration.initialWorldMap = worldMap
sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
}
ARWorldTrackingConfigurationのinitialWorldMapにセットしてsessionを起動すると、共有元の座標系と同じになるので、複数のデバイスで繋いでゲームするようなときに実装しやすそう。
例えばARCoreのCloud AnchorでもAnchorを共有することができて同じ場所に物を置く実装を容易に実現できるが、それだけでは座標系は一致していないので何らかの方法で座標系を合わせる必要がある。その証拠にGoogleが出しているJust A Lineのアプリでは、「2つのデバイスの位置を合わせてください」というメッセージが出てきている。同じ座標系にするのを簡単にするためだ。
ちなみにJust a lineのiOSのコードはgithubに公開されているのだが、ここではsetWorldOrigin(relativeTransform:)というメソッドを使って2つのデバイスの座標系を一致させている。
AppleのドキュメントではこのARWorldMapについて、
- Multiuser AR experiences. (複数人でのAR体験)
- Persistent AR experiences (永続的なAR体験)
という2点のAR体験の拡張に貢献すると紹介されていて、
前者はリアルタイムに同じ場所でAR体験をするようなゲームを想起させるし、
後者は例えば公園の特定の場所に何かを保存して、後から来た人が同じ場所に来た時にそれを発見できるといった体験を想起させる。
筆者の印象としては、iOS12のデバイスどうしで空間共有体験を実現するためにはARWorldMapを使うのがベストだ。もちろん世界の点群情報が集まったARCloudが提供される未来がくればそちらの方が良いかもしれない。
パフォーマンス向上
ImageTracking
https://developer.apple.com/documentation/arkit/arimagetrackingconfiguration
https://developer.apple.com/documentation/arkit/arimageanchor
今までは1枚ずつしか画像を検出できなかったが、今回から複数が可能になる。
そして、その認識の精度が向上し、画像が動いていても正確に追跡することができる。
configurationに画像を登録してから、ARSessionをRunすることで、該当の画像を認識することができるようになる。ARImageAnchorは自動的にSceneKitが発見してくれて、ARSessionDelegateやARSCNViewDelegateでanchorの発見をトラックできる。
ARKit1.5からARImageAnchorは使うことができるが、ARImageTrackingConfiguration がARKit2.0から。今まではARWorldTrackingConfigurationを使って同様なことができていたが、新しいconfigulationは画像が動いていても追跡できるという点でパフォーマンスが向上している。その代わりこのconfigulationだと平面認識などができない。
堤さんのブログのARKit 2.0の画像トラッキングとARKit 1.5の画像検出の違いがこの点について詳しい。
WWDC2018のWhat’s New in ARKit 2では、猫の静止画を認識し、その画像の上で動画を再生するというデモを行なっていた。
Face Detection
視線 | 舌 |
---|---|
Gaze DetectionとTongue Detectrionが追加された。
視線と舌の認識である。
より顔の動きを正確に認識することができるようになった。
こちらは現状iPhoneXだけで使える機能。今後とも対応デバイスが増えて行くであろう。
Faster Plane Detection
平面認識なども早くなったと言われている。
いつも2、3秒はARSessionの起動にかかるので、これが短くなるのは嬉しい。
まとめ
- 実世界にある物体の検出とその保存
- 実世界のマップ情報の保存、再現
これらは使いようによって、かなり面白いことができそうです。
仕事上、ARKit2.0は調べていくので、コードベースでも最新情報はどんどん追記していきます。
何か認識が間違っているものがあればお気軽に教えてください
公開されているサンプルコード
- Scanning and Detecting 3D Objects
- Creating a Multiuser AR Experience
- Creating a Game for Augmented Reality
- Adding Realistic Reflections to an AR Experience
- Creating a Persistent AR Experience
ARKit 2.0 参考資料
https://developer.apple.com/videos/play/wwdc2018/602
https://developer.apple.com/documentation/arkit