第2章 ARKit 堤 修一/@shu223
iOSにARフレームワークが標準搭載されることの大きな魅力のひとつは、これまでの10年のiOSの歴史の中で脈々と整えられてきた豊富な他のフレームワークと連携させられることでしょう。その中でも、ARKitと同様にiOSデバイスのカメラから得た画像を入力として利用できるCore ML・Visionとは非常に組み合わせやすく、なおかつAR&機械学習というホットな技術の組み合わせだけにデモとしてのインパクトもあります。
本節では、「Core ML+Visionで物体認識を行い、その物体にARKitで仮想のタグを付ける」アプリケーションの実装方法を解説します。
サンプルコード:09_ARObjectDetection
2.10.1 実装方針
「Core MLによる物体認識結果を、ARKitの3D空間内にテキストノードとして設置する」機能を実現するにあたって、「Core MLによる認識結果を、どのようにして3D空間の座標に紐付けるか」がポイントとなります。
たとえば物体認識の結果に対象の物体を囲む矩形の座標(2D画像内の座標)が入っている場合、簡単な方法だとその中心座標を求め、ARKitでヒットテストを行いヒットした位置(3D空間内の座標)にテキストノードを設置する、という方法が考えられます。
しかし、本節で利用するCore MLのモデルInceptionv3.mlmodel(Appleが公式に配布しているモデル)による物体認識の結果には、「認識した物体の座標」が含まれません。
そこで、VNCoreMLRequestのimageCropAndScaleOptionプロパティを用いて、入力画像の中心からクロップしたものを認識に利用するよう指定し、
request.imageCropAndScaleOption = .centerCrop
認識結果を設置する3D空間における座標には、「スクリーン座標の中心に対するヒットテスト結果」を用いることにします。画面中心にあるものを認識したはずなので、画面中心に見えているオブジェクト(実際には特徴点または平面)上に認識結果を示すテキストノードを設置しよう、という方針です。
2.10.2 Core ML・Vision・ARKit連携のポイント
Core MLの詳細は本書の「第3章 Core ML」を参照しつつ、ここではARKitとの連携のポイントとなる実装のみ解説します。
■毎フレームのカメラからの入力画像データへのアクセス
Core MLへ入力画像として渡すために、ARKitがカメラから毎フレーム取得している画像データを取得します。この画像データはARFrameのcapturedImageプロパティより得られます。
var capturedImage: CVPixelBuffer { get }
型はCVPixelBufferで、このバッファにカメラから得られたピクセルデータが入っています。
ARFrameオブジェクトはARKitのセッションにおいてフレームの更新があるたびに呼ばれるARSessionDelegateのsession(_:didUpdate:)メソッドの第2引数から得られるので、ここからピクセルバッファを取得することで毎フレームの処理を行えます。