Swift初心者のためのAIアプリ（画像認識編）


![output2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550611/c587f826-8049-cac3-6a08-c1887288e931.gif)

#◆はじめに
##今回作るもの
Swiftで「CoreML」という人工知能のライブラリを用いて、iPhoneのカメラで撮影したものが何であるのか判断するアプリを作成します。
#どんな人に
+ Swift初心者
+ 機械学習、理論じゃなくてまずは触ってみたい
+ 画像認識おもしろそう
+ とりあえずmacbookもってる
+ プログラミングなんかおもしろそう



##ーCoreMLとはー
まずは[こちら](https:developer.apple.com/machine-learning/)でAppleの機械学習のサイトに飛びましょう。

次に学習済みモデルのダウンロードを行います。
学習済みモデルとは、予め用意されている
今回はAppleが提供する、データを集め既に学習済みのモデルを使います。


<details><summary>ここで機械学習とは？？</summary><div>
>機械にデータを学習・分析させて分類や推定を行うことです。

>今回は、予め正解データを与えて新しいデータを処理する教師あり学習を使います。詳しい理論についてはここでは解説しません。（あくまでアプリ作成が目的なため）
</div></details>

#◆解説編
##流れ
> STEP0：今回使用する学習済みモデルのダウンロード
> STEP1：新規プロジェクトの作成
> STEP2：見た目の部分作成
> STEP3：step0でダウンロードしたものをアプリ内にいれます
> STEP4：実際にコードを書く
> 完成

##❏ STEP0 モデルのダウンロード

下の方の「Models」→「Browse models」の[リンク](https://developer.apple.com/machine-learning/models/)をクリックしてください。

今回はまず「Resnet50」というモデルを使いたいと思います。

<img width="300" alt="model1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550611/88e39fc6-b47a-f223-303d-a47cfac3c0eb.png">
<img width="300" alt="model2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550611/a6808fb5-52a1-9218-9a6c-1095bb84124a.png">

**この画像の一番上のやつをダウンロードしてください。**


##❏ STEP1　プロジェクトの追加
新しいプロジェクトを作成しましょう。
今回はiOSのAppで作成してください。

<details><summary>*参考画像*</summary><div>
![Screen Shot 2021-11-23 at 12.54.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550611/b3820726-f392-ec2c-3b64-3dad7e003311.png)
</div></details>

名前は適当に決めて大丈夫です。

##❏ STEP2 UI

UIを作りましょう。
Mainのストーリーボードを開き、以下のパーツを追加します。

1. Image View
2. Text View
3. Button

下の画像のように「Assitant」を開きましょう。
<details><summary>*参考画像*</summary><div>
![Screen Shot 2021-11-23 at 13.03.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550611/f07c96fa-d6ac-d920-dd60-f9818f4da9f3.png)
</div></details>

先程配置したパーツを「control」キーを推しながら「viewController」にドラッグ＆ドロップします。
場所は下の画像を参考にしてください。（初心者の方は全く同じようにしてください。）

<details><summary>*参考画像*</summary><div>
![Screen Shot 2021-11-23 at 13.01.39 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550611/6ccf01d8-38a9-031d-f30a-ed6451eb34cd.png)
</div></details>

今回は下のように名前をつけています。（この後コードをコピペする方は合わせてください。）
>Image View　→　imageView
>Text View → infoView
>Button → takeImage

また、Text View を「写真を撮ってください。 判定します！」に変更しておくと、アプリを使用する際にきれいにみえます。

##❏ STEP3 モデルをアプリへ
最初にダウンロードしたResnet50のモデルをドラッグ＆ドロップでアプリに入れてください。
下の画像のようになっていれば大丈夫です。
<details><summary>*参考画像*</summary><div>
![Screen Shot 2021-11-23 at 13.45.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550611/4a405b81-70f1-9c26-610f-29281ac0fd5e.png)
</div></details>

##❏ STEP4 コーディング
次にコードを記入していきます。
写真とコードを貼っておくので自分のコードと見比べながら追記していってください。

<details><summary>*コード全体像写真*</summary><div>
![Screen Shot 2021-11-23 at 13.28.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550611/abf6745f-cd4d-cd62-65f5-aca4fb0371ba.png)
</div></details>

##❏ STEP5 これ必須です
iPhoneでカメラ機能を使うために写真の設定を行います。
写真とコードを貼っておくので自分のコードと見比べながら追記していってください。
![スクリーンショット 2022-01-21 午後9.10.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550611/de7169a7-1fb7-bbc6-3702-198b81a05f90.png)



<details><summary>*全コード*</summary><div>

```swift
import UIKit
import CoreML
import Vision
import AVFoundation

class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
    
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var infoView: UITextView!

    var imagePicker: UIImagePickerController!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.sourceType = .camera
    }
    
    @IBAction func takeImage(_ sender: Any) {
        present(imagePicker, animated: true, completion: nil)
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        imageView.image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
        imagePicker.dismiss(animated: true, completion: nil)
        imageInference(image: (info[UIImagePickerController.InfoKey.originalImage] as? UIImage)!)
    }
    func imageInference(image: UIImage) {
        //モデルの定義（モデルを指定することで色々と変更できる:今回はResnet50）
        guard let model = try? VNCoreMLModel(for: Resnet50().model) else {
            fatalError("cannnot read the model")
        }

        let request = VNCoreMLRequest(model: model) {
            [weak self] request, error in
            
            guard let results = request.results as? [VNClassificationObservation],
                  let firstResult = results.first else {
                      fatalError("cannot judge it")
                  }
            
            DispatchQueue.main.async {
                self?.infoView.text = "Accuracy : \(Int(firstResult.confidence * 100))%, \n Lavel : \((firstResult.identifier))"
                let utterWords = AVSpeechUtterance(string: (self?.infoView.text)!)
                utterWords.voice = AVSpeechSynthesisVoice(language: "en-US")
                let synthesizer = AVSpeechSynthesizer()
                synthesizer.speak(utterWords)
            }
        }
        
        guard let ciImage = CIImage(image: image) else {
            fatalError("cannnot convert image")
        }
        
        let imageHandler = VNImageRequestHandler(ciImage: ciImage)
        
        DispatchQueue.global(qos: .userInteractive).async {
            do {
                try imageHandler.perform([request])
            } catch {
                print("error \(error)")
            }
        }
    }
    
}
```

</div></details>

##❏ STEP6 実行してみよう
このようになったら成功です。

![output2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550611/c587f826-8049-cac3-6a08-c1887288e931.gif)