获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

在 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类。

下一步