search
LoginSignup
6
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

ubiregiUbiregi Advent Calendar 2019 Day 17

posted at

updated at

Organization

iOS13とVision.frameworkで犬と猫に癒される

Ubiregi Advent Calendar 2019 17日目です。

今回はiOS13のVision.frameworkで新たに使えるようになったVNRecognizeAnimalsRequestを使って動物(🐶と🐱)を識別するアプリのサンプルを紹介します。

Vision.frameworkとは

e3663268-5db4-42c9-a7f0-2114920a9f1f.png
参照:https://developer.apple.com/documentation/coreml

  • iOS11から追加された画像や映像から人や文字など様々なものを識別するAPIを提供するApple標準フレームワーク
  • 機械学習フレームワークのCore MLを抽象化したもの
  • iOS13から新たに🐶と🐱の識別子が追加された🎉🎉🎉

やってみた

DogAndCatSample.gif

私の家には可愛いスクリーンショット 2019-02-01 18.02.39.pngがいて被写体としてちょうどいいんですが残念ながら🐶を検出できないため、
今回は止む無くネットから拾ってきた画像を使いカメラロールを経由して動物画像をVisionに解析してもらいCollectionViewControllerに表示するプログラムを作りました。

遷移先の画面で識別結果を表示しています。confidenceは信頼を返す値です。
二匹以上いる場合や、🐶と🐱が混じっている場合もそれぞれ認識されていますし、何気なく突っ込んだサングラス🐶や🐱もちゃんと識別されていることに驚きました。
カメラロールには、シュミレータに入っているデフォルトの風景画像以外に、猫に近い豹や虎などを含めてみましたが精度はとても高く結局画像が荒いものは精度は落ちました。

Simulator Screen Shot - iPhone 11 Pro Max - 2019-12-17 at 02.11.51.png

ライオンキングはネコでした。癒されているので問題ありません。

Simulator Screen Shot.png
液体になっているネコもネコでした。癒し。

Simulator Screen Shot - iPhone 11 Pro Max - 2019-12-17 at 04.08.51.png
!!!!ブサ可愛い。。

どうやっているのか

    private func searchAnimals(with datas: [Data], completion: @escaping () -> (Void)) {
        let group = DispatchGroup()
        let lock = NSLock()
        var searchIndex = 0

        let animalRecognitionRequest = VNRecognizeAnimalsRequest { [weak self] (request, error) in
            DispatchQueue.global(qos: .userInitiated).async {
                defer { lock.unlock() }
                guard let results = request.results as? [VNRecognizedObjectObservation], results.count > 0 else {
                    return
                }
                var detectionString = ""
                var animalCount = 0

                for result in results {
                    let animals = result.labels
                    for animal in animals {
                        animalCount = animalCount + 1
                        let animalType = animal.identifier == VNAnimalIdentifier.cat.rawValue ? "😸" : "🐶"
                        let string = "#\(animalCount) \(animal.identifier) \(animalType) confidence is \(animal.confidence)\n"
                        detectionString = detectionString + string
                    }
                }
                guard let self = self else { return }
                self.thumbnails.append(ThumbnailEntity(data: datas[searchIndex], detection: detectionString))
                self.output.insertItem(at: self.thumbnails.count - 1)
            }
        }

        let queue = DispatchQueue.global(qos: .userInitiated)
        for (i, data) in datas.enumerated() {
            group.enter()
            queue.async(group: group) {
                defer { group.leave() }
                lock.lock()
                guard let image = UIImage(data: data), let cgImage = image.cgImage else { return }
                searchIndex = i
                let requestHandler = VNImageRequestHandler(cgImage: cgImage, options: [:])
                try? requestHandler.perform([animalRecognitionRequest])
            }
        }

        group.notify(queue: .main) {
            completion()
        }
    }

説明

VNImageRequestHandlerに対してCGImageをセットしてVNRecognizeAnimalsRequest配列を渡して実行します。
するとVNRecognizedObjectObservation配列として結果が返ってきます。
この時に、一枚の画像の中にたくさんの🐶や🐱がいる場合もあるので配列で受け取ります。とても尊い配列です。
あとは🐶か🐱を判定するために、VNAnimalIdentifier.docVNAnimalIdentifier.catを使えば判定が可能です。
rawValueDogCat文字列です。
このサンプルコードでは、今後AppleのアップデートでVNAnimalIdentifierがたくさん増えると🐱以外は全て🐶になります。逆にしたら良かった。(そうじゃない)
今回画像データをループでまわして見つかり次第CollectionViewControllerinsertしているので排他制御を行うためのコードが入っています。普段、UIの更新はメインスレッドでやれば、くらいしかちゃんと気にしていなかったので勉強になりました。

サンプルコード

今回作ったサンプルはこちらです。ツッコミ所はいろいろあって例えば今回は画像が何百枚もあることを考えていません。
VIPERというUIアーキテクチャを採用して作ってみたのでその感想あたりもいろいろ書きたいんですが枠が残っていれば書こうかと思います。

最後に

Vision系のML技術はAppleのVision.framework以外にもたくさんあります。
例えば、
・Cloud Vision APIとCloud AutoML Vision
https://cloud.google.com/solutions/image-search-app-with-cloud-vision?hl=ja
・FirebaseのML Kitも画像のラベル付け機能をベータ版リリースしています。
https://firebase.google.com/docs/ml-kit/label-images

これらはGoogleの提供する機能ですが、iPhoneとandroidを比較すると画像に対する機能はiPhoneより一歩進んでいる印象です。
これらを使えばiOSでもandroidでも共通したAPIを利用できる利点がありますが、Appleのframeworkを使えば、サードパーティに頼らずサーバーレスでアプリ内で完結して使えるのも一つの強みだと思います。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
6
Help us understand the problem. What are the problem?