在 iOS 上使用 ML Kit 標記圖片

您可以使用 ML Kit 來標記影像中識別的對象,使用裝置上模型或雲模型。請參閱概述以了解每種方法的優點。

在你開始之前

  1. 如果您尚未將 Firebase 新增至您的應用程式中,請按照入門指南中的步驟進行操作。
  2. 在 Podfile 中包含 ML Kit 函式庫:
    pod 'Firebase/MLVision', '6.25.0'

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

    安裝或更新專案的 Pod 後,請務必使用其.xcworkspace開啟 Xcode 專案。
  3. 在您的應用程式中,導入 Firebase:

    迅速

    import Firebase

    Objective-C

    @import Firebase;
  4. 如果您想使用基於雲端的模型,並且尚未為您的專案啟用基於雲端的 API,請立即執行以下操作:

    1. 開啟 Firebase 控制台的ML Kit API 頁面
    2. 如果您尚未將項目升級到 Blaze 定價計劃,請按一下升​​級來執行此操作。 (只有當您的專案不在 Blaze 計劃中時,系統才會提示您升級。)

      只有 Blaze 等級的項目才能使用基於雲端的 API。

    3. 如果尚未啟用基於雲端的 API,請按一下啟用基於雲端的 API

    如果您只想使用裝置上的模型,可以跳過此步驟。

現在,您可以使用裝置上模型或基於雲端的模型來標記影像。

1. 準備輸入影像

使用UIImageCMSampleBufferRef建立VisionImage物件。

使用UIImage

  1. 如有必要,旋轉影像,使其imageOrientation屬性為.up
  2. 使用正確旋轉的UIImage建立VisionImage物件。不要指定任何旋轉元資料 - 必須使用預設值.topLeft

    迅速

    let image = VisionImage(image: uiImage)

    Objective-C

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

使用CMSampleBufferRef

  1. 建立一個VisionImageMetadata對象,該對象指定CMSampleBufferRef緩衝區中包含的圖像資料的方向。

    若要取得影像方向:

    迅速

    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;
      }
    }

    然後,建立元資料物件:

    迅速

    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. 使用CMSampleBufferRef物件和旋轉元資料建立VisionImage物件:

    迅速

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

    Objective-C

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

2. 配置並運行影像標記器

要標記影像中的對象,請將VisionImage物件傳遞給VisionImageLabelerprocessImage()方法。

  1. 首先,取得VisionImageLabeler的實例。

    如果您想使用裝置上的影像標記器:

    迅速

    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];
    

    如果您想使用雲端影像貼標機:

    迅速

    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()方法:

    迅速

    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物件的陣列將傳遞到完成處理程序。從每個物件中,您可以獲得有關圖像中識別的特徵的資訊。

例如:

迅速

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 取得結果,然後一步渲染影像並疊加。透過這樣做,每個輸入幀只需渲染到顯示表面一次。有關範例,請參閱展示範例應用程式中的PreviewOverlayViewFIRDetectionOverlayView類別。

下一步