Unityアプリ(iOS)でCoreMLを使う
「Unityアプリ(iOS)」で「CoreML」を使って画像分類を行う方法をまとめました。iOSプラグインの作成方法については、「UnityのiOSプラグインの作成」を参照。
1. 画像分類を行うクラスの作成
Xcodeを使って、画像分類クラス「ImageClassifier.swift」を作成します。Unityに組み込む前に、動作確認も行います。
◎ モデル
モデルはAppleの提供する「MobileNetV2Int8LUT.mlmodel」を使います。
◎ 画像
テスト用の画像も用意してプロジェクトに追加します。
・cat.jpg (256 x 256)
◎ ImageClassifier.swift
画像分類を行うコード「ImageClassifier.swift」を作成します。predict() にbase64形式の画像とコールバックを渡すと、推論結果をコールバックで返します。
import UIKit
import Vision
// 画像分類器
@objc public class ImageClassifier: NSObject {
@objc public static let shared = ImageClassifier() // シングルトン
var model = try! VNCoreMLModel(for: MobileNetV2Int8LUT().model) // モデル
// 予測
@objc public func predict(_ base64: String!, onCallback: ((NSString)->Void)!) {
// base64デコード
let data:Data! = Data(base64Encoded: base64, options:
Data.Base64DecodingOptions.ignoreUnknownCharacters)
//リクエストの生成
let request = VNCoreMLRequest(model: self.model) {
request, error in
// エラー処理
if error != nil {
onCallback(error!.localizedDescription as NSString)
return
}
// 検出結果の取得
let observations = request.results as! [VNClassificationObservation]
var text: String = "\n"
for i in 0..<min(3, observations.count) { //上位3件
let probabillity = Int(observations[i].confidence*100) //信頼度
let label = observations[i].identifier //ID
text += "\(label) : \(probabillity)%\n"
}
// コールバック
onCallback(text as NSString)
}
// リクエストの実行
let handler = VNImageRequestHandler(data:data, options:[:])
guard (try? handler.perform([request])) != nil else {return}
}
}
◎ ViewController.swift
テスト用のコード「ViewController.swift」も準備します。
import UIKit
// 画像分類のテスト
class ViewController: UIViewController {
// ビュー表示時に呼ばれる
override func viewDidAppear(_ animated: Bool) {
// イメージの読み込み
let image:UIImage! = UIImage(named:"cat")
// base64エンコード
let jpgData:Data! = image.jpegData(compressionQuality: 1.0);
let base64:String! = jpgData.base64EncodedString(options:
Data.Base64EncodingOptions.lineLength64Characters);
// 推論
ImageClassifier.shared.predict(base64) {result in
print(result as String);
}
}
}
◎ 実行
Egyptian cat : 12%
Angora, Angora rabbit : 10%
Siamese cat, Siamese : 7%
2. Unityプロジェクトの準備
Unityプロジェクトを準備します。
◎ 画像
画像「cat.jpg」を Assets/StreamingAssets に配置します。
◎ UI
UnityのUIを準備します。
(1) 「RawImage」を追加し、「ImageView」と名前を指定。
(2) 「Text」を追加し、「Label」と名前を指定。
(3) 空の「GameObject」を追加し、「ImageClassifier」と名前を指定し、スクリプト「ImageClassifier.cs」を追加。
「ImageClassifier.cs」のコードは次のとおり。
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.UI;
public class ImageClassifier : MonoBehaviour
{
[DllImport("__Internal")]
private static extern void Predict(string base64);
// 参照
public RawImage imageView;
public Text label;
// イメージ
private byte[] imageData;
private string result = "";
// スタート時に呼ばれる
public void Start()
{
// 画像の読み込み
this.imageData = File.ReadAllBytes(Application.streamingAssetsPath+"/cat.jpg");
// 画像の表示
Texture2D texture = new Texture2D(256, 256);
texture.LoadImage(this.imageData);
this.imageView.texture = texture;
// base64エンコード
string base64 = System.Convert.ToBase64String(this.imageData);
// 推論
Predict(base64);
}
// 結果の取得
public void OnResult(string result)
{
label.text = result;
}
}
◎ iOSプラグイン
iOSプラグイン「ImageClassifier.mm」をAssets/Pluginsに配置します。
#import <UnityFramework/UnityFramework-Swift.h>
#ifdef __cplusplus
extern "C" {
#endif
void Predict(char* base64) {
NSString *base64Str = [NSString stringWithCString:base64 encoding:NSUTF8StringEncoding];
[[ImageClassifier shared] predict:base64Str onCallback:^(NSString *str){
UnitySendMessage("ImageClassifier", "OnResult", (char *)[str UTF8String]);
}];
}
#ifdef __cplusplus
}
#endif
◎ Swiftコード
先程作成した「ImageClassifier.swift」をAssets/Plugins/iOSに配置します。
◎ ビルド
ビルドして、Xcodeプロジェクトを生成します。
3. モデルの追加
Xcodeプロジェクト生成後に、モデルの追加作業を行います。
(自動化したいけどできてない。)
(1) Xcodeプロジェクトに、「MobileNetV2Int8LUT.mlmodel」をドラッグ&ドロップ。ターゲットは「UnityFramework」を選択。
(2) 「UnityFramwork」の「General」でiOSのバージョンを「12」に上げる。
「ImageClassification.swift」で、iOS12以降の機能を使ってるので。
(3) Projectの「Build Settings」の「CoreML Model Compiler - Code Generation」の「CoreML Model Class Generation Language」で「Swift」を選択。
Objective-CとSwiftが混じってるプロジェクトのせいか、選択しないとエラーになります。
4. 実行
成功すると、以下のような画面が表示されます。
この記事が気に入ったらサポートをしてみませんか?