第2章 ARKit 堤 修一/@shu223


func session(_ session: ARSession, didUpdate frame: ARFrame) {
    let pixelBuffer = frame.capturedImage

 ARSCNViewを利用している場合は、ARSCNViewDelegateの(実際にはSCNSceneRendererDelegateの)renderer(_:updateAtTime:)メソッドから最新フレームのARFrameオブジェクトを取得し、ピクセルバッファにアクセスする方法もあります。

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    guard let frame = sceneView.session.currentFrame else {return}
    let pixelBuffer = frame.capturedImage

Core MLの認識を実行する

 ARKitから取得した毎フレームの画像データを、Core ML+Visionに渡します。

 VNImageRequestHandlerの初期化時に、引数に入力画像データを渡す必要がありますが、前項で解説した方法で得たCVPixelBufferオブジェクトをそのまま渡せます。

let handler = VNImageRequestHandler(cvPixelBuffer: imageBuffer)

 VNImageRequestHandlerが作成できたら、あとはperform()メソッドを呼ぶだけです。

try? handler.perform([request])     // requestはVNCoreMLRequestオブジェクト

Core MLの認識結果をテキストノードとして設置する

 Inceptionv3モデルを利用した場合、認識結果はVNClassificationObservationオブジェクトとして得られます。結果が得られたら、ARSCNViewhitTest(_:types:)メソッドによるヒットテスト注27)を、スクリーンの中心座標を対象に行います。そして、ヒットテスト結果を元にSCNTextをジオメトリに持つノードを設置します。

// 平面、特徴点を対象にヒットテストを実行
let results = sceneView.hitTest(screenCenterPos, types:
    [.existingPlaneUsingExtent, .featurePoint])
// 手前にある結果を取り出す
if let result = results.first {
    // SCNTextジオメトリを持つノード
    let tagNode = TagNode()
    // ヒットテスト結果のワールド変換行列をセット
    tagNode.transform = SCNMatrix4(hitTestResult.worldTransform)
    // シーンに設置
    sceneView.scene.rootNode.addChildNode(tagNode)
}

実際のサンプルではもう少し細かい制御をしていますが、ポイントは以上です。実行すると、図2.17のようにCore MLによる認識結果がARKitにより現実空間にタグ付けされます。

iOS 11 Programming

  • 著者:堤 修一,吉田 悠一,池田 翔,坂田 晃一,加藤 尋樹,川邉 雄介,岸川 克己,所 友太,永野 哲久,
  • 製本版,電子版
  • 続きを読む