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)"
}
})
上記のハンドラ内では、引数に入ってきた VNCoreMLRequest
の results
プロパティから 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関連記事
-
完全個人用なので実装は非常に雑です。 ↩