Как добавлять метки к изображениям с помощью ML Kit на iOS

С помощью ML Kit можно присваивать ярлыки объектам, распознанным на изображении. Модель по умолчанию, предоставляемая вместе с ML Kit, поддерживает более 400 разных ярлыков.

Попробовать

Подготовка

  1. Добавьте в Podfile следующие контейнеры ML Kit:
    pod 'GoogleMLKit/ImageLabeling', '8.0.0'
    
  2. После установки или обновления Pods проекта откройте проект Xcode, используя файл .xcworkspace. ML Kit поддерживается в Xcode версии 12.4 и более поздних.

Теперь вы готовы к разметке изображений.

1. Как подготовить входное изображение

Создайте объект VisionImage, используя UIImage или CMSampleBuffer.

Если вы используете UIImage, выполните следующие действия:

  • Создайте объект VisionImage с UIImage. Убедитесь, что вы указали правильный .orientation.

    Swift

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

    Objective-C

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

Если вы используете CMSampleBuffer, выполните следующие действия:

  • Укажите ориентацию изображения, содержащегося в CMSampleBuffer.

    Чтобы получить ориентацию изображения:

    Swift

    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 cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored
                                                                : UIImageOrientationRight;
    
        case UIDeviceOrientationLandscapeLeft:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored
                                                                : UIImageOrientationUp;
        case UIDeviceOrientationPortraitUpsideDown:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored
                                                                : UIImageOrientationLeft;
        case UIDeviceOrientationLandscapeRight:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored
                                                                : UIImageOrientationDown;
        case UIDeviceOrientationUnknown:
        case UIDeviceOrientationFaceUp:
        case UIDeviceOrientationFaceDown:
          return UIImageOrientationUp;
      }
    }
          
  • Создайте объект VisionImage, используя объект CMSampleBuffer и ориентацию:

    Swift

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

2. Как настроить и запустить инструмент для распознавания объектов на изображениях

Чтобы добавить метки к объектам на изображении, передайте объект VisionImage в метод processImage() класса ImageLabeler.

  1. Сначала получите экземпляр ImageLabeler.

Swift

let labeler = ImageLabeler.imageLabeler()

// Or, to set the minimum confidence required:
// let options = ImageLabelerOptions()
// options.confidenceThreshold = 0.7
// let labeler = ImageLabeler.imageLabeler(options: options)

Objective-C

MLKImageLabeler *labeler = [MLKImageLabeler imageLabeler];

// Or, to set the minimum confidence required:
// MLKImageLabelerOptions *options =
//         [[MLKImageLabelerOptions alloc] init];
// options.confidenceThreshold = 0.7;
// MLKImageLabeler *labeler =
//         [MLKImageLabeler imageLabelerWithOptions:options];
  1. Затем передайте изображение методу 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 *_Nullable labels,
            NSError *_Nullable error) {
   if (error != nil) { return; }

   // Task succeeded.
   // ...
}];

3. Как получать информацию о помеченных объектах

Если распознавание изображений прошло успешно, обработчик завершения получает массив объектов ImageLabel. Каждый объект ImageLabel представляет собой элемент, помеченный на изображении. Базовая модель поддерживает более 400 разных ярлыков. Вы можете получить текстовое описание каждого ярлыка, его индекс среди всех ярлыков, поддерживаемых моделью, и оценку достоверности совпадения. Пример:

Swift

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

Советы по повышению эффективности в реальном времени

Если вы хотите присваивать ярлыки изображениям в приложении, работающем в реальном времени, следуйте приведенным ниже рекомендациям, чтобы достичь наилучшей частоты кадров.

  • Для обработки кадров видео используйте синхронный API results(in:) для распознавания изображений. Вызовите этот метод из функции captureOutput(_, didOutput:from:) объекта AVCaptureVideoDataOutputSampleBufferDelegate, чтобы синхронно получить результаты для заданного кадра видео. Оставьте для свойства alwaysDiscardsLateVideoFrames объекта AVCaptureVideoDataOutput значение true, чтобы ограничить вызовы к инструменту распознавания изображений. Если во время работы инструмента появится новый кадр видео, он будет пропущен.
  • Если вы используете результаты распознавания объектов для наложения графики на входное изображение, сначала получите результат от ML Kit, а затем отрисуйте изображение и наложите графику за один шаг. В этом случае отрисовка на поверхности экрана выполняется только один раз для каждого обработанного входного кадра. Пример можно найти в функции updatePreviewOverlayViewWithLastFrame в образце быстрого запуска ML Kit.