見出し画像

SwiftUIでCoreML。

機械学習CoreMLです。Vision.Frameworkを使った認識については以前書きましたが

https://note.com/dngri/n/n976634143c43

今回はCoreMLを使って画像認識のアプリを作ってみます。

モデルはAppleのサイトにあるものを使います。

MobileNetV2FP16をダウンロードしてXcodeに入れて使います。

画像1

Xcode上で"MobileNetV2FP16"を選択すれば情報が表示されます。それをみると、

Detects the dominant objects present in an image from a set of 1001 categories such as trees, animals, food, vehicles, person etc. The top-1 accuracy from the original publication is 74.7%.

trees, animals, food, vehicles, person(木、動物、食べ物、乗り物、人)が認識できるみたいです。

参考の動画です。

Xcodeを使っていきます。

import SwiftUI
struct ContentView: View {
   @State private var currentInd = 1
   @State var label:String = "Hellow"
   var photos = ["cat","dog"]
 
   var body: some View {
       VStack{
           Text(label)
           Image(photos[currentInd])
           Button("この画像は何?"){
              
           }
       }
   }
}

まず、SwiftUIでの表示部分です。Text,画像,ボタンという並びです。

Text()
Image()
Button(""){}

あとほそれぞれ見た目と機能となる関数、あと一番大事なCoreMLの学習済みモデルを読み込んでいきます。

CoreMLの学習済みモデルの読み込みですが、Vision.Framework又はとモデルそのものを使って読み込むことができます。今回はモデルそのものを読み込みますが、大事なことがあります。この場合ははUIimage()に機能を追加、拡張たものを用意しておかないとうまく行かないようです。以下参考サイトです。(UIimageExtension.swiftを今回は作って追加しました。変数名など少し変更しています)

ボタンを押した時に画像の最適化。この場合は画像を判定しやすいように大きさを、変更する命令を作っておかなと行けるみたいです。

モデルの読み込みですが

 let model = MobileNetV2FP16()

で良いです。モデルの名前に"()"をつけてやればOK!

このモデルをボタンを押すことで画像がなんであるかを推測させます。

その時必要なのが変数、"@State"で情報を即時更新させる変数を作っています。

@State private var currentInd = 1
@State var label:String = "Hellow"

変数としては

@State private var currentInd = 1
@State var label:String = "Hellow"
var photos = ["cat","dog"]
let model = MobileNetV2FP16()

を使っていきます。

それでは心臓部分の関数ですが、

   private func classfication(){
       let currentImageName = photos[currentInd]
       let img = UIImage(named: currentImageName)
       guard  let resized = img?.resizeTo(CGSize(width: 224, height: 224)),
       let buffer = resized.toBuffer() else {return}
       let output = try? model.prediction(image: buffer)
       if let output = output{
           self.label = output.classLabel
       }
   }

となりますが、

let currentImageName = photos[currentInd]
let img = UIImage(named: currentImageName)

写真をUIimageに変換して"img"変数に代入します。

guard let resized = img?.resizeTo(CGSize(width: 224, height: 224)),
let buffer = resized.toBuffer() else {return}

写真の大きさを認識できる大きさにリサイズして"CVPixelBuffer"(メインメモリ内のピクセルを保持するイメージバッファ)に変換します。

ここ大事です。

let output = try? model.prediction(image: buffer)
if let output = output{
self.label = output.classLabel
}

あとは"model.prediction"で推測させ"label"に答えを表示させます。

画像2

"MobileNetV2FP16"ファイルの赤枠部分"Prediction"の部分に入力の方法、表示させるなど出力の方法が書いてあるので指示に従います。

あと必要なこととしては写真を用意すること今回は、

var photos = ["cat","dog"]

2枚の写真"cat","dog""Asset.xcassets"に入れています。

@State private var currentInd = 1

で指定した写真を推測します。実行してみます。

画像3

全コードです。

import SwiftUI
struct ContentView: View {
   
   @State private var currentInd = 1
   @State var label:String = "Hellow"
   var photos = ["cat","dog"]
   let model = MobileNetV2FP16()
   
   private func classfication(){
       let currentImageName = photos[currentInd]
       let img = UIImage(named: currentImageName)
       guard  let resized = img?.resizeTo(CGSize(width: 224, height: 224)),
       let buffer = resized.toBuffer() else {return}
       let output = try? model.prediction(image: buffer)
       if let output = output{
           self.label = output.classLabel
       }
   }
   
   var body: some View {
       VStack{
           Text(label)
           Image(photos[currentInd])
           .resizable()
           .frame(width:200,height: 150)
           Button("この画像は何?"){
               self.classfication()
           }
           
       }
       
   }
}

いいなと思ったら応援しよう!