ML Kit を使用して画像にラベルを付ける(iOS)

ML Kit を使用すると、端末モデルまたはクラウドモデルを使って、画像内で認識されたオブジェクトにラベルを付けることができます。それぞれの手法の利点については、概要をご覧ください。

始める前に

  1. まだアプリに Firebase を追加していない場合は、スタートガイドの手順に沿って追加してください。
  2. ML Kit ライブラリを Podfile に含めます:
    pod 'Firebase/MLVision', '6.25.0'

    # If using the on-device API: pod 'Firebase/MLVisionLabelModel', '6.25.0'

    プロジェクトの Pod をインストールまたは更新した後に、.xcworkspace を使用して Xcode プロジェクトを開くようにしてください。
  3. アプリに Firebase をインポートします。

    Swift

    import Firebase

    Objective-C

    @import Firebase;
  4. Cloud ベース モデルを使用する場合に、まだプロジェクトで Cloud ベースの API を有効にしていないときは、ここで有効にします。

    1. Firebase コンソールの ML Kit API ページを開きます。
    2. まだプロジェクトを Blaze 料金プランにアップグレードしていない場合は、[アップグレード] をクリックしてアップグレードします(プロジェクトをアップグレードするよう求められるのは、プロジェクトが Blaze プランでない場合のみです)。

      Blaze レベルのプロジェクトだけが Cloud ベースの API を使用できます。

    3. Cloud ベースの API がまだ有効になっていない場合は、[Cloud ベースの API を有効化] をクリックします。

    デバイスモデルのみを使用する場合は、この手順を省略できます。

これで、デバイスモデルまたはクラウドベース モデルを使用して画像にラベルを付ける準備ができました。

1. 入力画像を準備する

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

UIImage を使用するには:

  1. 必要に応じて、imageOrientation プロパティが .up になるように画像を回転させます。
  2. 適切に回転させた UIImage を使用して VisionImage オブジェクトを作成します。回転メタデータにはデフォルト値の .topLeft を使用する必要があるため、値を指定しないでください。

    Swift

    let image = VisionImage(image: uiImage)

    Objective-C

    FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

CMSampleBufferRef を使用するには:

  1. VisionImageMetadata オブジェクトを作成し、CMSampleBufferRef バッファに格納されている画像データの向きを指定します。

    画像の向きは次のように取得します。

    Swift

    func imageOrientation(
        deviceOrientation: UIDeviceOrientation,
        cameraPosition: AVCaptureDevice.Position
        ) -> VisionDetectorImageOrientation {
        switch deviceOrientation {
        case .portrait:
            return cameraPosition == .front ? .leftTop : .rightTop
        case .landscapeLeft:
            return cameraPosition == .front ? .bottomLeft : .topLeft
        case .portraitUpsideDown:
            return cameraPosition == .front ? .rightBottom : .leftBottom
        case .landscapeRight:
            return cameraPosition == .front ? .topRight : .bottomRight
        case .faceDown, .faceUp, .unknown:
            return .leftTop
        }
    }

    Objective-C

    - (FIRVisionDetectorImageOrientation)
        imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                               cameraPosition:(AVCaptureDevicePosition)cameraPosition {
      switch (deviceOrientation) {
        case UIDeviceOrientationPortrait:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationLeftTop;
          } else {
            return FIRVisionDetectorImageOrientationRightTop;
          }
        case UIDeviceOrientationLandscapeLeft:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationBottomLeft;
          } else {
            return FIRVisionDetectorImageOrientationTopLeft;
          }
        case UIDeviceOrientationPortraitUpsideDown:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationRightBottom;
          } else {
            return FIRVisionDetectorImageOrientationLeftBottom;
          }
        case UIDeviceOrientationLandscapeRight:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationTopRight;
          } else {
            return FIRVisionDetectorImageOrientationBottomRight;
          }
        default:
          return FIRVisionDetectorImageOrientationTopLeft;
      }
    }

    次に、メタデータ オブジェクトを作成します。

    Swift

    let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
    let metadata = VisionImageMetadata()
    metadata.orientation = imageOrientation(
        deviceOrientation: UIDevice.current.orientation,
        cameraPosition: cameraPosition
    )

    Objective-C

    FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init];
    AVCaptureDevicePosition cameraPosition =
        AVCaptureDevicePositionBack;  // Set to the capture device you used.
    metadata.orientation =
        [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                     cameraPosition:cameraPosition];
  2. VisionImage オブジェクトと回転メタデータを使用して CMSampleBufferRef オブジェクトを作成します。

    Swift

    let image = VisionImage(buffer: sampleBuffer)
    image.metadata = metadata

    Objective-C

    FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
    image.metadata = metadata;

2. 画像ラベラーを構成して実行する

画像内のオブジェクトにラベルを付けるには、VisionImage オブジェクトを VisionImageLabelerprocessImage() メソッドに渡します。

  1. まず、VisionImageLabeler のインスタンスを取得します。

    デバイスの画像ラベラーを使用する場合:

    Swift

    let labeler = Vision.vision().onDeviceImageLabeler()
    
    // Or, to set the minimum confidence required:
    // let options = VisionOnDeviceImageLabelerOptions()
    // options.confidenceThreshold = 0.7
    // let labeler = Vision.vision().onDeviceImageLabeler(options: options)
    

    Objective-C

    FIRVisionImageLabeler *labeler = [[FIRVision vision] onDeviceImageLabeler];
    
    // Or, to set the minimum confidence required:
    // FIRVisionOnDeviceImageLabelerOptions *options =
    //         [[FIRVisionOnDeviceImageLabelerOptions alloc] init];
    // options.confidenceThreshold = 0.7;
    // FIRVisionImageLabeler *labeler =
    //         [[FIRVision vision] onDeviceImageLabelerWithOptions:options];
    

    クラウドの画像ラベラーを使用する場合:

    Swift

    let labeler = Vision.vision().cloudImageLabeler()
    
    // Or, to set the minimum confidence required:
    // let options = VisionCloudImageLabelerOptions()
    // options.confidenceThreshold = 0.7
    // let labeler = Vision.vision().cloudImageLabeler(options: options)
    

    Objective-C

    FIRVisionImageLabeler *labeler = [[FIRVision vision] cloudImageLabeler];
    
    // Or, to set the minimum confidence required:
    // FIRVisionCloudImageLabelerOptions *options =
    //         [[FIRVisionCloudImageLabelerOptions alloc] init];
    // options.confidenceThreshold = 0.7;
    // FIRVisionImageLabeler *labeler =
    //         [[FIRVision vision] cloudImageLabelerWithOptions:options];
    
  2. 次に、画像を processImage() メソッドに渡します。

    Swift

    labeler.process(image) { labels, error in
        guard error == nil, let labels = labels else { return }
    
        // Task succeeded.
        // ...
    }
    

    Objective-C

    [labeler processImage:image
               completion:^(NSArray<FIRVisionImageLabel *> *_Nullable labels,
                            NSError *_Nullable error) {
                   if (error != nil) { return; }
    
                   // Task succeeded.
                   // ...
               }];
    

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

画像のラベル付けに成功すると、VisionImageLabel オブジェクトの配列が完了ハンドラに渡されます。各オブジェクトから、画像内で認識された特徴に関する情報を取得できます。

次に例を示します。

Swift

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

Objective-C

for (FIRVisionImageLabel *label in labels) {
   NSString *labelText = label.text;
   NSString *entityId = label.entityID;
   NSNumber *confidence = label.confidence;
}

リアルタイムのパフォーマンスを改善するためのヒント

リアルタイムのアプリケーションでラベルイメージを使用する場合は、適切なフレームレートを得るために次のガイドラインに従ってください。

  • 画像ラベラーの呼び出しのスロットル調整を行います。イメージ ラベラーの実行中に新しい動画フレームが使用可能になった場合は、そのフレームをドロップします。
  • イメージ ラベラーの出力を使用して入力画像の上にグラフィックスをオーバーレイする場合は、まず ML Kit から検出結果を取得し、画像とオーバーレイを 1 つのステップでレンダリングします。これにより、ディスプレイ サーフェスへのレンダリングは入力フレームごとに 1 回で済みます。例については、ショーケース サンプルアプリの previewOverlayView クラスと FIRDetectionOverlayView クラスをご覧ください。

次のステップ