iPhoneでCore MLを使って画像識別する

## はじめに
今世間ではApple vision proが盛り上がってますが、最近iPhoneアプリ開発の勉強をしているので今更かよって内容になります。（本当はapple vision pro買って色々試してみたい）
さて始めます。
今回はAppleから出ているCore MLを活用して画像識別を行なっていく。
Core MLとはすでに公開されているモデルを活用したり、自分でモデルを作成することによって機械学習を行うことができるフレームワークである。
以下から公式のドキュメントを参照できるが詳細に入ると全部英語なので私は毎回絶望している

https://developer.apple.com/jp/documentation/coreml/

大枠の構成はこのようになっています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645607/c026b363-2d08-7820-4b09-d4ec0ebfc6ab.png)

### Vision
画像や動画から特徴を検出し分類、認識などができ画像解析や分析ができる。

### Natural Language
自然言語処理を用いて言語の識別などができるらしい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645607/cad95547-df82-66dd-45f7-2f91a935bbea.png)


### Speech
音声認識を行い。音声からテキストへの変換ができる。

### Sound Analysis
音声から何の音かを特定することが出来るらしい。公式では笑い声や拍手を特定できると書いてあった。


### 公式に掲載されている素晴らしいモデル一覧

https://developer.apple.com/jp/machine-learning/models/

正直機械学習やったこともないので、まだモデルを作ることも出来ない私みたいなヘッポコエンジニアにはとてもありがたいモデルばかりだと思っている。モデルのインポートをするだけでiPhoneでも画像識別ができるのはいい時代だなぁと



# 実装していく
ちょっと前段が長くなりましたが、今回は公開されているモデルのinceptionv3を使って画像識別していきます。何を識別するかですが、画像が犬か犬じゃないかを識別しようと思います。
strybord使ってるので全く一緒の実装やコピペしたければ参考までに

inceptionv3とは？
100万個を超えるイメージデータを学習しているらしい。助かる。

https://jp.mathworks.com/help/deeplearning/ref/inceptionv3.html

モデルはここからダウンロード
その後プロジェクトに埋め込む

https://docs-assets.developer.apple.com/coreml/models/Inceptionv3.mlmodel

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645607/00cd2f63-2ce2-0a3a-47fd-2bc9b7ac8d2b.png)

```swift
//以下フレームワークのインポートをViewControllerに追記
import CoreML
import Vision
```

詳細ステップは割愛してコードを公開します


```swift
//
//  ViewController.swift
//  CheckApp
//
//  Created by 井手翔平 on 2024/02/17.
//

//フレームワークをインポートする
import UIKit
import CoreML
import Vision

//ビュー用のクラス
class ViewController: UIViewController, UIImagePickerControllerDelegate,UINavigationControllerDelegate{

    @IBOutlet weak var imageView: UIImageView!
    let imagePicker = UIImagePickerController()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        //画像の初期設定みたいなもの
        //tyoeで.cameraにすればカメラで撮った画像にできる
        imagePicker.delegate = self
        imagePicker.sourceType = .photoLibrary
        imagePicker.allowsEditing = false
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        
        if let userPickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
            imageView.image = userPickedImage
            
            guard let ciimage = CIImage(image:userPickedImage) else {
                fatalError("画像変換が失敗した")
            }
            detect(image: ciimage)
        }
        imagePicker.dismiss(animated: true, completion: nil)
    }
    
    func detect(image:CIImage) {
        guard let model = try? VNCoreMLModel(for: Inceptionv3().model) else {
            fatalError("modelみつけれなかったよ")
        }
        
        let request = VNCoreMLRequest(model: model) {(request, error) in
            guard let results = request.results as? [VNClassificationObservation] else {
                fatalError("model faild to proess image.")
            }
            if let firstResult = results.first{
                print(firstResult)
                if firstResult.identifier.contains("Rottweiler") {
                    self.navigationItem.title = "この写真の犬はRottweiler！！"
                } else {
                    self.navigationItem.title = "おっと、この写真はRottweilerじゃないぜ、、、"
                }
            }
        }
        let handler = VNImageRequestHandler(ciImage: image)
        
        do {
            try handler.perform([request])
        }
        catch{
            print(error)
        }
    }

    @IBAction func cameraTapped(_ sender: UIBarButtonItem) {
        present(imagePicker, animated: true, completion: nil)
    }
    

}


```
## 実機へビルドした結果
この可愛い犬の写真を識別してみた
画像については以下からダウンロード

https://www.pexels.com/ja-jp/

![19D9178F-CBA3-4ECE-8E9A-E783534E38E3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645607/a4278e39-c8ef-f543-0e86-2b746686b2e5.jpeg)

### 結果
すいません画像の比率がおかしくなって、元の画像が何かも分かりませんが、犬種は特定できています。
![5603CFD0-8706-4489-B5D1-0D2CEB062858.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645607/a6429074-facd-3311-7b93-ae5477b39829.png)


他の画像でelse側の動作確認やってみる。最近読んだ本の画像があったのでこちらで、、、
![492E0A94-F3B2-44A9-8B4B-5566D40DC779_1_102_o.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645607/5a164703-9e70-1726-f87a-ca16e0f2727a.jpeg)

### else側の結果
220万部のとこがやけに拡大されてますが、識別としては問題ない！アプリとしては良くないが画像識別はOKということで。
![062336F3-F149-43AD-BD2A-3ABC89592323_1_102_o.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645607/2c053aa5-19c1-da3c-ad86-12de5eeb0e89.jpeg)


どこで学習モデルからの値を判別してるかはコードを見れば分かると思いますが、参考までに
先程はなかったprintを追加してます。ここでどんな値が返ってきてるかを確認できる。
ちなみに最初の犬の画像だとこんな感じで返ってきていた。
VNCoreMLRequestRevision1 confidence=0.608663 "Rottweiler"
```swift
        let request = VNCoreMLRequest(model: model) {(request, error) in
            guard let results = request.results as? [VNClassificationObservation] else {
                fatalError("model faild to proess image.")
            }
            if let firstResult = results.first{
            //コンソールへ出力してみると返ってきている値が何かわかるよ
                print(firstResult)
                if firstResult.identifier.contains("Rottweiler") {
                    self.navigationItem.title = "この写真の犬はRottweiler！！"
                } else {
                    self.navigationItem.title = "おっと、この写真はRottweilerじゃないぜ、、、"
                }
            }
        }
```

## 最後に
機械学習やったことが全くなくても、iPhoneではcore mlを活用する事で簡単に画像分析が出来る事が分かった。
ちなみに今回はif文で、該当するかしないかを判別して表示していたが、titleにそのまま判別時の戻り値を設定する事で、何を識別したかをアプリ上でリアルタイムにみる事も可能です。