iOS
画像処理
機械学習
Keras
coreML

Core ML+Visionを用いた物体認識の最小実装

iOS 11 より追加される Core ML を使うと、Keras や Caffe や scikit-learn で学習させたモデルをコマンドラインツールで変換でき、それをXcodeにドラッグ&ドロップすれば必要なコードが自動生成される、とのこと。

"Vision Framework: Building on Core ML" というWWDC17のセッションに付随する公式サンプルで、Core MLでつくったカスタムモデル+Visionフレームワークで画像の識別(MNISTの手書き数字認識)をやる実装があるのですが、その実装を参考にCore ML+Visionでリアルタイム物体認識を実装してみました。

このキャプチャはiOS 11のものではなくiOS-10-Samplerのものです。NDAに配慮してこちらを載せましたが、同じ Inception v3 モデルなので、動作としては同じです。

実装手順

1. AVFoundationを用いて、リアルタイムカメラ入力処理を実装する

毎フレームの CMSampleBuffer もしくは CVPixelBuffer を取得するようにするための実装。ここは新APIではないので、詳細は省略しますが、私はiOS-10-Sampler等でもやっている実装をずっと使いまわしています。

私はこういうカメラ入力を使ったサンプルをよくつくるので、自作ラッパー 1 +コードスニペットを利用して、すぐに実装できるようにしてます。

2. .mlmodel ファイルをプロジェクトにドラッグ&ドロップ

プロジェクトのツリーからは見えませんが、モデル名と同様のSwiftクラスが自動生成されます。

今回はAppleが配布している Inceptionv3.mlmodel を利用したので、Inceptionv3.swift が自動生成されました。

3. VNCoreMLRequest を作成

VNCoreMLRequest オブジェクトを保持するプロパティを用意しておいて、

private var coremlRequest: VNCoreMLRequest!

VNCoreMLMode オブジェクトと、CNNの計算処理が完了した後に実行される VNRequestCompletionHandler型のハンドラを渡します。

let model = try! VNCoreMLModel(for: Inceptionv3().model)
coremlRequest = VNCoreMLRequest(model: model, completionHandler: { (request, error) in
    guard let observations = request.results as? [VNClassificationObservation] else { fatalError() }
    guard let best = observations.first else { fatalError() }

    DispatchQueue.main.async {
        self.predictLabel.text = "Classification: \"\(best.identifier)\" Confidence: \(best.confidence)"
    }
})

上記のハンドラ内では、引数に入ってきた VNCoreMLRequestresults プロパティから VNClassificationObservation型の結果のリストを取り出し、第1位の候補をUIに表示するようにしています。(エラーハンドリング系はコードをシンプルにするために省略)

ちなみにAppleのサンプルでは、VNCoreMLRequest を以下のように lazy オプションで初期化してましたが、

lazy var classificationRequest: VNCoreMLRequest = {

これだといざ認識を実行するときになってモデルの読み込み等諸々の準備処理が走ることになるので、良くないんじゃ...と思い上のようにしました。

所感

Core MLを導入することで、Metal Performance Shadersのレイヤにまったく触ることなく、ポインタがどうのこうのとかをやることもなく、非常に簡単に、GPU Acceleratedなリアルタイム物体認識ができてしまいました。簡単すぎてショックです。

今回やってみて「次はこのあたりを見てみよう」と思ったのが以下の2点

  • 自動生成されたコードの中身
  • Visionを使わずCore MLだけで書くとどうなるのか?(Visionは何をやってくれてるのか?)
    • 今回のケースでは入出力の橋渡し(CIImage -> Inceptionv3Input / Inceptionv3Output -> [VNClassificationObservation])をしてくれてるだけ?
  • Core MLのモデルを使わない、Visionのビルトイン機能を一通り試す

近いうちにまた記事を書こうと思います。

iOS 11関連記事


  1. 完全個人用なので実装は非常に雑です。