はじめに
CreateMLとRoboflow、SwiftUIという3種の神器を使うことによって、オリジナルAIと画像認識アプリを作ることができます。
完成物
今回は、画像に写っているトマトを検出し、それが腐っているかどうか判別するアプリを作りましょう。
Roboflow Universeからデータセットをダウンロードしよう
CreateMLでAIモデルを作るには、データのディレクトリ構造をCreateMLが読み取れる形にする必要があります。簡単にCreateML形式でデータセットをダウンロードできるRoboflow Universeを使いましょう。
まずはこのサイトにアクセスしましょう。
右上からCreate an Account
をしましょう。
中央から欲しいデータセットを調べます。
今回は腐ったトマトなのでrotten tomato
など調べてみましょう。
今回はこれを使っていきます。
左からDataset
を選択します。
右にあるCreateML JSON
をクリックしましょう。
Download zip to computer
を選択し、Continue
をクリックします。
解凍するとこのようなフォルダが出てきます。
CreateMLでモデルを学習させよう
プロジェクトの作成
Xcodeを開き、Xcode > Open Developer Tool > Create ML
と選びます。
左下のNew Document
を選びます。
今回はObject Detection
を選びましょう。
プロジェクト名を入力します。
右下からCreate
を選択しましょう。
このような画面が出てきたら成功です!
モデルの学習
Training Data
のプラスボタンを押しましょう。
先ほどダウンロードしたデータの中のtrain
フォルダを選択します。
このように表示されたら、左上のTrain
をクリックしましょう!
(右にあるVaridationやTestingも追加することは可能ですが、追加しなかった場合は自動でテストを行なってくれます)
学習中はこのような画面が表示されます。(かなり時間がかかるかもしれません)
時間がかかりすぎる場合はIterationを下げましょう。
学習が終わったら、Output
を選び、右上のGet
をクリックしましょう!
保存できたら、このようなmlpackage
が生成されます。
アプリを作成しよう
Xcodeで新しいプロジェクトを作成しましょう。
先ほど作成したmlpackage
をドラッグ&ドロップでXcodeに追加しましょう。
ContentView.swift
を以下のように書き換えていきます。
import SwiftUI
import PhotosUI
import CoreML
import Vision
struct ContentView: View {
@State private var image: UIImage?
@State private var results: [TomatoDetectionResult] = []
@State private var showImagePicker = false
var body: some View {
VStack {
if let image = image {
Image(uiImage: image)
.resizable()
.scaledToFit()
.frame(height: 300)
} else {
Text("アルバムから写真を選択してください")
.padding()
}
Button("アルバムを開く") {
showImagePicker = true
}
.padding()
.sheet(isPresented: $showImagePicker) {
ImagePicker(image: $image) { newImage in
self.image = newImage
detectTomatoes(in: newImage)
}
}
List(results) { result in
VStack(alignment: .leading) {
Text(result.isFresh ? "新鮮" : "腐っている")
.font(.headline)
Text("信頼度: \(String(format: "%.2f", result.confidence * 100))%")
.font(.subheadline)
}
}
}
}
private func detectTomatoes(in image: UIImage) {
guard let model = try? VNCoreMLModel(for: RottenTomatoDetector().model) else { return }
let request = VNCoreMLRequest(model: model) { request, _ in
guard let results = request.results as? [VNRecognizedObjectObservation] else { return }
self.results = results.map { observation in
let confidence = observation.confidence
let label = observation.labels.first?.identifier ?? "未知"
let isFresh = (label == "fresh")
return TomatoDetectionResult(isFresh: isFresh, confidence: confidence)
}
}
if let ciImage = CIImage(image: image) {
let handler = VNImageRequestHandler(ciImage: ciImage, options: [:])
try? handler.perform([request])
}
}
}
struct TomatoDetectionResult: Identifiable {
let id = UUID()
let isFresh: Bool
let confidence: Float
}
ただし、以下の部分は、上で作成したmlpackage
の名前に揃えるようにしてください。
guard let model = try? VNCoreMLModel(for: RottenTomatoDetector().model) else { return }
↑↑ここの部分↑↑
実行すれば、目標だったアプリが完成します!
その他のデータセット入手方法
代表的なものがKaggleです。
ここから入手したデータセットは必ずしもCreateMLの形式に準拠してるとは限らないため、データセットのディレクトリ構造を調節する、という手順が必要になることがあります。
まとめ
AIをつくる、だったり、画像分類アプリを作る、というのは一見難しそうでこのように基礎は簡単に作れるものです。
個人的にはハッカソンなど短期の大会で力を発揮すると考えているので、ぜひ使っていきましょう!