LoginSignup
8
6

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-11-23

output2.gif

◆はじめに

今回作るもの

Swiftで「CoreML」という人工知能のライブラリを用いて、iPhoneのカメラで撮影したものが何であるのか判断するアプリを作成します。

どんな人に

  • Swift初心者
  • 機械学習、理論じゃなくてまずは触ってみたい
  • 画像認識おもしろそう
  • とりあえずmacbookもってる
  • プログラミングなんかおもしろそう

ーCoreMLとはー

まずはこちらでAppleの機械学習のサイトに飛びましょう。

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

ここで機械学習とは??

機械にデータを学習・分析させて分類や推定を行うことです。

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

◆解説編

流れ

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

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

下の方の「Models」→「Browse models」のリンクをクリックしてください。

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

model1
model2

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

❏ STEP1 プロジェクトの追加

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

参考画像

Screen Shot 2021-11-23 at 12.54.08.png

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

❏ STEP2 UI

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

  1. Image View
  2. Text View
  3. Button

下の画像のように「Assitant」を開きましょう。

参考画像

Screen Shot 2021-11-23 at 13.03.13.png

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

参考画像

Screen Shot 2021-11-23 at 13.01.39 (3).png

今回は下のように名前をつけています。(この後コードをコピペする方は合わせてください。)

Image View → imageView
Text View → infoView
Button → takeImage

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

❏ STEP3 モデルをアプリへ

最初にダウンロードしたResnet50のモデルをドラッグ&ドロップでアプリに入れてください。
下の画像のようになっていれば大丈夫です。

参考画像

Screen Shot 2021-11-23 at 13.45.42.png

❏ STEP4 コーディング

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

コード全体像写真

Screen Shot 2021-11-23 at 13.28.34.png

❏ STEP5 これ必須です

iPhoneでカメラ機能を使うために写真の設定を行います。
写真とコードを貼っておくので自分のコードと見比べながら追記していってください。
スクリーンショット 2022-01-21 午後9.10.59.png

全コード
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)")
            }
        }
    }

}

❏ STEP6 実行してみよう

このようになったら成功です。

output2.gif

8
6
0

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
  3. You can use dark theme
What you can do with signing up
8
6