2017年09月11日

TensorFlow (Keras)とCore MLでリアルタイムの顔識別アプリを作ったぞい

エモトです.今週はAppleの発表会に,iOSDC JAPAN 2017と,iOS開発界隈のイベントが目白押しですね.iOSDCには弊社エンジニアも参加します.関係者各様よろしくお願いします.

n番煎じではありますが,機械学習フレームワーク TensorFlowKeras で学習したモデルを,iOS11 からの Core ML に与えて,簡単な顔識別のアプリを試作して見ました.試作ということで,データ収集など一部で手を抜いてます.ご了承ください.

IMG_0032 2.PNG


ただいま絶賛放送中のNEW GAME!!の9人の主要キャラを対象した識別アプリです.UI等は,先行実装された記事を参考しました.ありがとうございます.

1. TensorFlow (Keras)

画像データはGoogle画像検索およびTumblrタグ検索のスクリプトを書いて集めました.APIの使用制限上,各キャラごとに多くの画像は集められなかったのですが,比較的キャラの描き分けがされている,作画が安定しているからたぶん大丈夫だろうと思います.

使用したCNN(畳み込みニューラルネットワーク)は以下のような簡単なものを設定しました.

model = Sequential()
model.add(Conv2D(32,
                 kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

訓練およびテストデータには,取得した画像にOpenCVでアニメ顔検出を行い,顔領域を切り出したものを使用しました.Tumblrで取得した画像データを訓練,Googleで取得した画像データをテストとして,学習しました.

Epoch 81/1000
128/730 [====>.........................] - ETA: 2s - loss: 0.0728 - acc: 0.9609
256/730 [=========>....................] - ETA: 1s - loss: 0.0667 - acc: 0.9727
384/730 [==============>...............] - ETA: 1s - loss: 0.0610 - acc: 0.9766
512/730 [====================>.........] - ETA: 0s - loss: 0.0636 - acc: 0.9785
640/730 [=========================>....] - ETA: 0s - loss: 0.0629 - acc: 0.9797
730/730 [==============================] - 7s - loss: 0.0611 - acc: 0.9808 - val_loss: 0.4857 - val_acc: 0.8301
Epoch 00080: early stopping

学習結果は,EarlyStoppingを設定して,80回目の試行で切り上げ.テストデータに対して精度0.8となったので,遊び程度ならまあまあ良いかなと思います.本当はもっとデータ増やしたりやCNNを考えて,精度を上げたいところですが.

2. mlmodel へ変換

coremltools を使って,Kerasで学習したモデルをCore MLが読み込めるファイルへと変換します.convertのパラメータ調整もですが,Python2.7系にしか対応していないので,環境作成に時間かかりました.

import coremltools
coreml_model = coremltools.converters.keras.convert(h5_path, input_names = 'image', is_bgr = True, image_scale = 0.00392156863, image_input_names = 'image', class_labels = 'labels.txt')
coreml_model.save(mlmodel_path)

3. Core MLで識別

流れとしては,AVCaptureSessionでカメラから静止画像を順次受け取って顔画像を切り出して,Core MLで識別の流れです.ほかのブログ等では顔画像の識別はVisionフレームワークを使用してる例が多いですが.この試作アプリではアニメ顔ゆえにOpenCVで行なっています.本当は領域認識もRCNN,YOLOやSSDなどを実装して一緒に推論したいところですが,今回はそこまで手を回せられなかったので

    // 予測
    func predicate(image: UIImage) {
        
        let image = CIImage(cgImage: image.cgImage!)
        let handler = VNImageRequestHandler(ciImage: image)
        do {
            let model = try VNCoreMLModel(for: self.newGameModel.model)
            let req = VNCoreMLRequest(model: model, completionHandler: self.handleClassification)
            try handler.perform([req])
        } catch {
            self.isComputing = false
            print(error)
        }
    }
    
    // 推定結果
    private func handleClassification(request: VNRequest, error: Error?) {
        
        guard let observations = request.results as? [VNClassificationObservation] else { fatalError() }
        guard let best = observations.first else { fatalError() }
        
        DispatchQueue.main.async {
        	// 識別した結果に対応する処理など
            print("best identifier: " + best.identifier + ", prob: " + String(best.confidence*100))
            var str:String = ""
            for ob in observations {
                str = str + ob.identifier + ", " + String(ob.confidence*100) + "%" + "\n"
            }
            print(str)            
        }
    }

Core MLでリアルタイム識別を走らせてると,端末が熱くなってくるんですよね.画像一枚ごとに識別するシーンより,時系列データで連続したデータを識別するシーンがこれから多くなると思うので,ちょっと不安になります.近々発表される新型 iPhone はこの計算に耐えられる高スペックのCPUやGPUを積んでくるんでしょうか.楽しみです.
posted by Seesaa京都スタッフ at 11:37| Comment(0) | iOS | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント: