Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

iOSでAutoMLトレーニング済みモデルを使用して画像にラベルを付ける

あなたは後AutoMLビジョンエッジを使用して、独自のモデルを訓練するには、ラベル画像にアプリでそれを使用することができます。

AutoML VisionEdgeからトレーニングされたモデルを統合する方法は2つあります。モデルのファイルをXcodeプロジェクトにコピーしてモデルをバンドルすることも、Firebaseから動的にダウンロードすることもできます。

モデルバンドルオプション
アプリにバンドルされています
  • モデルはバンドルの一部です
  • iOSデバイスがオフラインの場合でも、モデルはすぐに利用可能です
  • Firebaseプロジェクトは必要ありません
Firebaseでホスト
  • アップロードしてモデルをホストFirebase機械学習
  • アプリバンドルのサイズを縮小します
  • モデルはオンデマンドでダウンロードされます
  • アプリを再公開せずにモデルの更新をプッシュする
  • 簡単にA / BとテストFirebaseリモートコンフィグ
  • Firebaseプロジェクトが必要

あなたが始める前に

  1. MLキットライブラリをPodfileに含めます。

    モデルをアプリにバンドルする場合:

    pod 'GoogleMLKit/ImageLabelingCustom'
    

    動的Firebaseからモデルをダウンロードするために、追加LinkFirebase依存関係を:

    pod 'GoogleMLKit/ImageLabelingCustom'
    pod 'GoogleMLKit/LinkFirebase'
    
  2. あなたのプロジェクトのポッドをインストールまたはアップデートした後、その使用してXcodeプロジェクトを開く.xcworkspace 。 MLキットはXcodeバージョン12.2以降でサポートされています。

  3. あなたがモデルをダウンロードしたい場合は、確認してくださいあなたのAndroidプロジェクトにFirebaseを追加あなたはまだ行っていない場合は、。モデルをバンドルする場合、これは必要ありません。

1.モデルをロードします

ローカルモデルソースを構成する

モデルをアプリにバンドルするには:

  1. Firebaseコンソールからダウンロードしたzipアーカイブからモデルとそのメタデータをフォルダーに抽出します。

    your_model_directory
      |____dict.txt
      |____manifest.json
      |____model.tflite
    

    3つのファイルはすべて同じフォルダーにある必要があります。ダウンロードしたファイルは、変更せずに(ファイル名を含めて)使用することをお勧めします。

  2. あなたがそうするとき、フォルダの参照を作成]を選択して世話をして、Xcodeプロジェクトにフォルダをコピーします。モデルファイルとメタデータはアプリバンドルに含まれ、MLキットで利用できます。

  3. 作成LocalModelモデルマニフェストファイルへのパスを指定して、オブジェクトを:

    迅速

    guard let manifestPath = Bundle.main.path(
        forResource: "manifest",
        ofType: "json",
        inDirectory: "your_model_directory"
    ) else { return true }
    let localModel = LocalModel(manifestPath: manifestPath)
    

    Objective-C

    NSString *manifestPath =
        [NSBundle.mainBundle pathForResource:@"manifest"
                                      ofType:@"json"
                                 inDirectory:@"your_model_directory"];
    MLKLocalModel *localModel =
        [[MLKLocalModel alloc] initWithManifestPath:manifestPath];
    

Firebaseでホストされているモデルソースを設定する

リモートでホストされたモデルを使用するには、作成CustomRemoteModelあなたはそれを公開したときにモデルを割り当てられた名前を指定して、オブジェクトを:

迅速

// Initialize the model source with the name you assigned in
// the Firebase console.
let remoteModelSource = FirebaseModelSource(name: "your_remote_model")
let remoteModel = CustomRemoteModel(remoteModelSource: remoteModelSource)

Objective-C

// Initialize the model source with the name you assigned in
// the Firebase console.
MLKFirebaseModelSource *firebaseModelSource =
    [[MLKFirebaseModelSource alloc] initWithName:@"your_remote_model"];
MLKCustomRemoteModel *remoteModel =
    [[MLKCustomRemoteModel alloc] initWithRemoteModelSource:firebaseModelSource];

次に、モデルのダウンロードタスクを開始し、ダウンロードを許可する条件を指定します。モデルがデバイスにない場合、またはモデルの新しいバージョンが利用可能な場合、タスクはFirebaseからモデルを非同期でダウンロードします。

迅速

let downloadConditions = ModelDownloadConditions(
  allowsCellularAccess: true,
  allowsBackgroundDownloading: true
)

let downloadProgress = ModelManager.modelManager().download(
  remoteModel,
  conditions: downloadConditions
)

Objective-C

MLKModelDownloadConditions *downloadConditions =
    [[MLKModelDownloadConditions alloc] initWithAllowsCellularAccess:YES
                                         allowsBackgroundDownloading:YES];

NSProgress *downloadProgress =
    [[MLKModelManager modelManager] downloadRemoteModel:remoteModel
                                             conditions:downloadConditions];

多くのアプリは初期化コードでダウンロードタスクを開始しますが、モデルを使用する前であればいつでもダウンロードできます。

モデルから画像ラベラーを作成します

あなたのモデルソースを設定した後、作成ImageLabelerうちの1からオブジェクトを。

あなたはローカルでのみバンドルモデルを持っている場合は、ちょうどあなたからラベラーを作成LocalModelオブジェクトとあなたが(参照要求したい信頼スコア閾値設定モデルを評価します):

迅速

let options = CustomImageLabelerOptions(localModel: localModel)
options.confidenceThreshold = NSNumber(value: 0.0)  // Evaluate your model in the Cloud console
                                                    // to determine an appropriate value.
let imageLabeler = ImageLabeler.imageLabeler(options)

Objective-C

CustomImageLabelerOptions *options =
    [[CustomImageLabelerOptions alloc] initWithLocalModel:localModel];
options.confidenceThreshold = @(0.0f);  // Evaluate your model in the Cloud console
                                        // to determine an appropriate value.
MLKImageLabeler *imageLabeler =
    [MLKImageLabeler imageLabelerWithOptions:options];

リモートでホストされているモデルを使用している場合は、実行する前に、モデルがダウンロードされていることを確認する必要があります。あなたは、モデル管理者の使用してモデルのダウンロードタスクのステータスを確認することができますisModelDownloaded(remoteModel:)方法を。

あなただけのラベラーを実行する前にこのことを確認する必要がありますが、リモートでホストされているモデルとローカルにバンドルモデルの両方を持っている場合、それはインスタンス化するとき、このチェックを実行するのは意味がありますImageLabeler :それはだ場合、リモートモデルからラベラーを作成ダウンロードされ、それ以外の場合はローカルモデルからダウンロードされます。

迅速

var options: CustomImageLabelerOptions
if (ModelManager.modelManager().isModelDownloaded(remoteModel)) {
  options = CustomImageLabelerOptions(remoteModel: remoteModel)
} else {
  options = CustomImageLabelerOptions(localModel: localModel)
}
options.confidenceThreshold = NSNumber(value: 0.0)  // Evaluate your model in the Firebase console
                                                    // to determine an appropriate value.
let imageLabeler = ImageLabeler.imageLabeler(options: options)

Objective-C

MLKCustomImageLabelerOptions *options;
if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) {
  options = [[MLKCustomImageLabelerOptions alloc] initWithRemoteModel:remoteModel];
} else {
  options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:localModel];
}
options.confidenceThreshold = @(0.0f);  // Evaluate your model in the Firebase console
                                        // to determine an appropriate value.
MLKImageLabeler *imageLabeler =
    [MLKImageLabeler imageLabelerWithOptions:options];

リモートでホストされているモデルしかない場合は、モデルがダウンロードされたことを確認するまで、モデル関連の機能(UIのグレーアウトや非表示など)を無効にする必要があります。

オブザーバーをデフォルトの通知センターに接続することで、モデルのダウンロードステータスを取得できます。弱参照を使用してくださいselfのダウンロードは多少時間がかかることがあり、元のオブジェクトは、時間によってダウンロードが終了を解放することができるので、オブザーバのブロックに。例えば:

迅速

NotificationCenter.default.addObserver(
    forName: .mlkitMLModelDownloadDidSucceed,
    object: nil,
    queue: nil
) { [weak self] notification in
    guard let strongSelf = self,
        let userInfo = notification.userInfo,
        let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue]
            as? RemoteModel,
        model.name == "your_remote_model"
        else { return }
    // The model was downloaded and is available on the device
}

NotificationCenter.default.addObserver(
    forName: .mlkitMLModelDownloadDidFail,
    object: nil,
    queue: nil
) { [weak self] notification in
    guard let strongSelf = self,
        let userInfo = notification.userInfo,
        let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue]
            as? RemoteModel
        else { return }
    let error = userInfo[ModelDownloadUserInfoKey.error.rawValue]
    // ...
}

Objective-C

__weak typeof(self) weakSelf = self;

[NSNotificationCenter.defaultCenter
    addObserverForName:MLKModelDownloadDidSucceedNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

              MLKRemoteModel *model = note.userInfo[MLKModelDownloadUserInfoKeyRemoteModel];
              if ([model.name isEqualToString:@"your_remote_model"]) {
                // The model was downloaded and is available on the device
              }
            }];

[NSNotificationCenter.defaultCenter
    addObserverForName:MLKModelDownloadDidFailNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

              NSError *error = note.userInfo[MLKModelDownloadUserInfoKeyError];
            }];

2.入力画像を準備します

作成VisionImage使用して、オブジェクトUIImageまたはCMSampleBufferRef

あなたが使用している場合はUIImage 、次の手順を実行します。

  • 作成VisionImageでオブジェクトをUIImage 。正しい指定してください.orientation

    迅速

    let image = VisionImage(image: uiImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

あなたが使用している場合はCMSampleBufferRef 、次の手順を実行します。

  • 含まれる画像データの向きを指定CMSampleBufferRefバッファ。

    画像の向きを取得するには:

    迅速

    func imageOrientation(
      deviceOrientation: UIDeviceOrientation,
      cameraPosition: AVCaptureDevice.Position
    ) -> UIImage.Orientation {
      switch deviceOrientation {
      case .portrait:
        return cameraPosition == .front ? .leftMirrored : .right
      case .landscapeLeft:
        return cameraPosition == .front ? .downMirrored : .up
      case .portraitUpsideDown:
        return cameraPosition == .front ? .rightMirrored : .left
      case .landscapeRight:
        return cameraPosition == .front ? .upMirrored : .down
      case .faceDown, .faceUp, .unknown:
        return .up
      }
    }
          

    Objective-C

    - (UIImageOrientation)
      imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                             cameraPosition:(AVCaptureDevicePosition)cameraPosition {
      switch (deviceOrientation) {
        case UIDeviceOrientationPortrait:
          return position == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored
                                                          : UIImageOrientationRight;
    
        case UIDeviceOrientationLandscapeLeft:
          return position == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored
                                                          : UIImageOrientationUp;
        case UIDeviceOrientationPortraitUpsideDown:
          return position == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored
                                                          : UIImageOrientationLeft;
        case UIDeviceOrientationLandscapeRight:
          return position == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored
                                                          : UIImageOrientationDown;
        case UIDeviceOrientationUnknown:
        case UIDeviceOrientationFaceUp:
        case UIDeviceOrientationFaceDown:
          return UIImageOrientationUp;
      }
    }
          
  • 作成VisionImage使用してオブジェクトをCMSampleBufferRefオブジェクトと向きを:

    迅速

    let image = VisionImage(buffer: sampleBuffer)
    image.orientation = imageOrientation(
      deviceOrientation: UIDevice.current.orientation,
      cameraPosition: cameraPosition)

    Objective-C

     MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
     image.orientation =
       [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                    cameraPosition:cameraPosition];

3.画像ラベラーを実行します

非同期:

迅速

imageLabeler.process(image) { labels, error in
    guard error == nil, let labels = labels, !labels.isEmpty else {
        // Handle the error.
        return
    }
    // Show results.
}

Objective-C

[imageLabeler
    processImage:image
      completion:^(NSArray<MLKImageLabel *> *_Nullable labels,
                   NSError *_Nullable error) {
        if (label.count == 0) {
            // Handle the error.
            return;
        }
        // Show results.
     }];

同期的に:

迅速

var labels: [ImageLabel]
do {
    labels = try imageLabeler.results(in: image)
} catch let error {
    // Handle the error.
    return
}
// Show results.

Objective-C

NSError *error;
NSArray<MLKImageLabel *> *labels =
    [imageLabeler resultsInImage:image error:&error];
// Show results or handle the error.

4.ラベル付きオブジェクトに関する情報を取得します

画像のラベリング処理が成功した場合、それはの配列を返しImageLabel 。各ImageLabel画像で標識したものを表しています。各ラベルのテキストの説明(TensorFlow Liteモデルファイルのメタデータで利用可能な場合)、信頼スコア、およびインデックスを取得できます。例えば:

迅速

for label in labels {
  let labelText = label.text
  let confidence = label.confidence
  let index = label.index
}

Objective-C

for (MLKImageLabel *label in labels) {
  NSString *labelText = label.text;
  float confidence = label.confidence;
  NSInteger index = label.index;
}

リアルタイムのパフォーマンスを向上させるためのヒント

リアルタイムアプリケーションで画像にラベルを付ける場合は、次のガイドラインに従って、最高のフレームレートを実現してください。

  • スロットルが検出器を呼び出します。検出器の実行中に新しいビデオフレームが使用可能になった場合は、フレームをドロップします。
  • 検出器の出力を使用して入力画像にグラフィックをオーバーレイする場合は、最初に結果を取得してから、画像とオーバーレイを1つのステップでレンダリングします。そうすることで、入力フレームごとに1回だけ表示面にレンダリングします。参照previewOverlayViewFIRDetectionOverlayView例えばショーケースのサンプルアプリのクラスを。