3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

えーえすAdvent Calendar 2024

Day 11

CreateMLとRoboflow Universeで画像認識アプリを作ろう!

Last updated at Posted at 2024-12-10

はじめに

CreateMLとRoboflow、SwiftUIという3種の神器を使うことによって、オリジナルAIと画像認識アプリを作ることができます。

完成物

今回は、画像に写っているトマトを検出し、それが腐っているかどうか判別するアプリを作りましょう。

IMG_8838.PNG

Roboflow Universeからデータセットをダウンロードしよう

CreateMLでAIモデルを作るには、データのディレクトリ構造をCreateMLが読み取れる形にする必要があります。簡単にCreateML形式でデータセットをダウンロードできるRoboflow Universeを使いましょう。

まずはこのサイトにアクセスしましょう。

右上からCreate an Accountをしましょう。

image.png

中央から欲しいデータセットを調べます。

image.png

今回は腐ったトマトなのでrotten tomatoなど調べてみましょう。

今回はこれを使っていきます。

左からDatasetを選択します。

1.png

右にあるCreateML JSONをクリックしましょう。

image.png

Download zip to computerを選択し、Continueをクリックします。

image.png

解凍するとこのようなフォルダが出てきます。

スクリーンショット 2024-12-06 14.25.06.png

CreateMLでモデルを学習させよう

プロジェクトの作成

Xcodeを開き、Xcode > Open Developer Tool > Create MLと選びます。

スクリーンショット 2024-12-06 14.27.43.png

左下のNew Documentを選びます。

スクリーンショット 2024-12-07 11.38.53.png

今回はObject Detectionを選びましょう。

スクリーンショット 2024-12-07 11.39.07.png

プロジェクト名を入力します。

スクリーンショット 2024-12-07 11.39.22.png

右下からCreateを選択しましょう。

スクリーンショット 2024-12-07 11.39.30.png

このような画面が出てきたら成功です!

スクリーンショット 2024-12-07 11.39.38.png

モデルの学習

Training Dataのプラスボタンを押しましょう。

スクリーンショット 2024-12-07 11.39.45.png

先ほどダウンロードしたデータの中のtrainフォルダを選択します。

スクリーンショット 2024-12-07 11.40.21.png

このように表示されたら、左上のTrainをクリックしましょう!
(右にあるVaridationやTestingも追加することは可能ですが、追加しなかった場合は自動でテストを行なってくれます)

スクリーンショット 2024-12-07 11.48.05.png

学習中はこのような画面が表示されます。(かなり時間がかかるかもしれません)

スクリーンショット 2024-12-09 13.55.28.png

時間がかかりすぎる場合はIterationを下げましょう。

学習が終わったら、Outputを選び、右上のGetをクリックしましょう!

スクリーンショット 2024-12-09 13.57.21.png

保存できたら、このようなmlpackageが生成されます。

スクリーンショット 2024-12-09 13.58.11.png

アプリを作成しよう

Xcodeで新しいプロジェクトを作成しましょう。

先ほど作成したmlpackageをドラッグ&ドロップでXcodeに追加しましょう。

スクリーンショット 2024-12-09 23.48.27.png

ContentView.swiftを以下のように書き換えていきます。

ContentView
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 }
                                          ↑↑ここの部分↑↑

実行すれば、目標だったアプリが完成します!

IMG_8838.PNG

その他のデータセット入手方法

代表的なものがKaggleです。

ここから入手したデータセットは必ずしもCreateMLの形式に準拠してるとは限らないため、データセットのディレクトリ構造を調節する、という手順が必要になることがあります。

まとめ

AIをつくる、だったり、画像分類アプリを作る、というのは一見難しそうでこのように基礎は簡単に作れるものです。
個人的にはハッカソンなど短期の大会で力を発揮すると考えているので、ぜひ使っていきましょう!

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?