在 Apple 平台上使用 Firebase 機器學習為圖片加上標籤

您可以使用 Firebase ML 為圖片中辨識到的物件加上標籤。如要瞭解此 API 的功能,請參閱總覽

事前準備

    如果您尚未在應用程式中加入 Firebase,請按照入門指南中的步驟操作。

    使用 Swift Package Manager 安裝及管理 Firebase 依附元件。

    1. 在 Xcode 中保持開啟應用程式專案,然後依序點選「File」(檔案) 和「Add Packages」(新增 Package)
    2. 系統提示時,請新增 Firebase Apple 平台 SDK 存放區:
    3.   https://github.com/firebase/firebase-ios-sdk.git
    4. 選擇 Firebase ML 程式庫。
    5. -ObjC 標記新增至目標的建構設定「Other Linker Flags」部分。
    6. 完成後,Xcode 就會自動開始在背景中解析並下載依附元件。

    接下來,請執行一些應用程式內設定:

    1. 在應用程式中匯入 Firebase:
      SwiftObjective-C
      import FirebaseMLModelDownloader
      @import FirebaseMLModelDownloader;
  1. 如果您尚未為專案啟用雲端 API,請立即進行:

    1. Firebase 控制台中開啟 Firebase ML API 頁面
    2. 如果您尚未將專案升級至即付即用 Blaze 定價方案,請按一下「Upgrade」進行升級 (只有在專案未採用 Blaze 定價方案時,系統才會提示您升級)。

      只有採用 Blaze 定價方案的專案才能使用雲端 API。

    3. 如果您尚未啟用雲端 API,請按一下「啟用雲端 API」

您現在可以開始為圖片加上標籤。

1. 準備輸入圖片

使用 UIImageCMSampleBufferRef 建立 VisionImage 物件。

如何使用 UIImage

  1. 如有需要,請旋轉圖片,讓其 imageOrientation 屬性為 .up
  2. 使用正確旋轉的 UIImage 建立 VisionImage 物件。請勿指定任何旋轉中繼資料,必須使用預設值 .topLeft
    SwiftObjective-C
    let image = VisionImage(image: uiImage)
    FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

如何使用 CMSampleBufferRef

  1. 建立 VisionImageMetadata 物件,指定 CMSampleBufferRef 緩衝區所含圖片資料的方向。

    如要取得圖片方向,請按照下列步驟操作:

    SwiftObjective-C
    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
        }
    }
    - (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;
      }
    }

    接著,建立中繼資料物件:

    SwiftObjective-C
    let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
    let metadata = VisionImageMetadata()
    metadata.orientation = imageOrientation(
        deviceOrientation: UIDevice.current.orientation,
        cameraPosition: cameraPosition
    )
    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 物件:
    SwiftObjective-C
    let image = VisionImage(buffer: sampleBuffer)
    image.metadata = metadata
    FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
    image.metadata = metadata;

2. 設定及執行圖片標註工具

如要為圖片中的物件加上標籤,請將 VisionImage 物件傳遞至 VisionImageLabelerprocessImage() 方法。

  1. 首先,請取得 VisionImageLabeler 的例項:

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

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

3. 取得標記物件的相關資訊

如果圖片標記成功,系統會將 VisionImageLabel 物件的陣列傳遞至完成處理常式。您可以從每個物件取得圖像中辨識到的功能資訊。

例如:

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

後續步驟