Помечайте изображения с помощью модели, обученной AutoML, на iOS.

После обучения собственной модели с помощью AutoML Vision Edge вы можете использовать ее в своем приложении для маркировки изображений.

Существует два способа интеграции моделей, обученных с помощью AutoML Vision Edge. Вы можете связать модель, скопировав файлы модели в свой проект Xcode, или вы можете динамически загрузить ее из Firebase.

Варианты комплектации модели
Включено в ваше приложение
  • Модель входит в комплект.
  • Модель доступна сразу, даже когда iOS-устройство находится в автономном режиме.
  • Нет необходимости в проекте Firebase
Размещено на Firebase
  • Разместите модель, загрузив ее в Firebase Machine Learning.
  • Уменьшает размер пакета приложений
  • Модель скачивается по запросу.
  • Отправляйте обновления модели без повторной публикации приложения.
  • Простое A/B-тестирование с помощью Firebase Remote Config
  • Требуется проект Firebase

Попробуйте это

Прежде чем вы начнете

1. Включите библиотеки ML Kit в свой подфайл:

Для объединения модели с вашим приложением:
    pod 'GoogleMLKit/ImageLabelingAutoML'
    
Для динамической загрузки модели из Firebase добавьте зависимость LinkFirebase :
    pod 'GoogleMLKit/ImageLabelingAutoML'
    pod 'GoogleMLKit/LinkFirebase'
    
2. После установки или обновления модулей проекта откройте проект Xcode, используя его код .xcworkspace >. ML Kit поддерживается в Xcode версии 13.2.1 или новее. 3. Если вы хотите загрузить модель , обязательно добавьте Firebase в свой проект iOS , если вы еще этого не сделали. Это не требуется при объединении модели.

1. Загрузите модель

Настройте источник локальной модели

Чтобы связать модель с вашим приложением:

1. Извлеките модель и ее метаданные из zip-архива, который вы скачали с консоли Firebase, в папку:
    your_model_directory
      |____dict.txt
      |____manifest.json
      |____model.tflite
    
Все три файла должны находиться в одной папке. Мы рекомендуем использовать файлы в том виде, в котором вы их скачали, без изменений (включая имена файлов).

2. Скопируйте папку в свой проект Xcode, не забывая при этом выбирать «Создать ссылки на папки» . Файл модели и метаданные будут включены в пакет приложения и доступны в ML Kit.

3. Создайте объект AutoMLImageLabelerLocalModel , указав путь к файлу манифеста модели:

Быстрый

guard let manifestPath = Bundle.main.path(
    forResource: "manifest",
    ofType: "json",
    inDirectory: "your_model_directory"
) else { return }
let localModel = AutoMLImageLabelerLocalModel(manifestPath: manifestPath)

Цель-C

NSString *manifestPath =
    [NSBundle.mainBundle pathForResource:@"manifest"
                                  ofType:@"json"
                             inDirectory:@"your_model_directory"];
MLKAutoMLImageLabelerLocalModel *localModel =
    [[MLKAutoMLImageLabelerLocalModel alloc] initWithManifestPath:manifestPath];

Настройте источник модели, размещенный в Firebase

Чтобы использовать удаленно размещенную модель, создайте объект AutoMLImageLabelerRemoteModel , указав имя, которое вы присвоили модели при ее публикации:

Быстрый

let remoteModel = AutoMLImageLabelerRemoteModel(
    name: "your_remote_model"  // The name you assigned in
                               // the Firebase console.
)

Цель-C

MLKAutoMLImageLabelerRemoteModel *remoteModel =
    [[MLKAutoMLImageLabelerRemoteModel alloc]
        initWithName:@"your_remote_model"];  // The name you assigned in
                                             // the Firebase console.

Затем запустите задачу загрузки модели, указав условия, при которых вы хотите разрешить загрузку. Если модели нет на устройстве или доступна более новая версия модели, задача асинхронно загрузит модель из Firebase:

Быстрый

let downloadConditions = ModelDownloadConditions(
  allowsCellularAccess: true,
  allowsBackgroundDownloading: true
)

let downloadProgress = ModelManager.modelManager().download(
  remoteModel,
  conditions: downloadConditions
)

Цель-C

MLKModelDownloadConditions *downloadConditions =
    [[MLKModelDownloadConditions alloc] initWithAllowsCellularAccess:YES
                                         allowsBackgroundDownloading:YES];

NSProgress *downloadProgress =
    [[MLKModelManager modelManager] downloadModel:remoteModel
                                       conditions:downloadConditions];

Многие приложения запускают задачу загрузки в своем коде инициализации, но вы можете сделать это в любой момент, прежде чем вам понадобится использовать модель.

Создайте маркировщик изображений на основе своей модели.

После настройки источников модели создайте объект ImageLabeler на основе одного из них.

Если у вас есть только локально связанная модель, просто создайте метку из объекта AutoMLImageLabelerLocalModel и настройте требуемый порог оценки достоверности (см. Оценка вашего режима :

Быстрый

let options = AutoMLImageLabelerOptions(localModel: localModel)
options.confidenceThreshold = NSNumber(value: 0.0)  // Evaluate your model in the Firebase console
                                                    // to determine an appropriate value.
let imageLabeler = ImageLabeler.imageLabeler(options: options)

Цель-C

MLKAutoMLImageLabelerOptions *options =
    [[MLKAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
options.confidenceThreshold = @(0.0);  // Evaluate your model in the Firebase console
                                       // to determine an appropriate value.
MLKImageLabeler *imageLabeler =
    [MLKImageLabeler imageLabelerWithOptions:options];

Если у вас есть удаленно размещенная модель, вам придется убедиться, что она загружена, прежде чем запускать ее. Вы можете проверить состояние задачи загрузки модели с помощью метода isModelDownloaded (remoteModel:) менеджера моделей.

Хотя вам нужно подтвердить это только перед запуском средства разметки, если у вас есть как удаленно размещенная модель, так и локально связанная модель, возможно, имеет смысл выполнить эту проверку при создании экземпляра ImageLabeler : создайте средство разметки из удаленной модели, если оно скачано, а из локальной модели иначе.

Быстрый

var options: AutoMLImageLabelerOptions!
if (ModelManager.modelManager().isModelDownloaded(remoteModel)) {
  options = AutoMLImageLabelerOptions(remoteModel: remoteModel)
} else {
  options = AutoMLImageLabelerOptions(localModel: localModel)
}
options.confidenceThreshold = NSNumber(value: 0.0)  // Evaluate your model in the Firebase console
                                                    // to determine an appropriate value.
let imageLabeler = ImageLabeler.imageLabeler(options: options)

Цель-C

MLKAutoMLImageLabelerOptions *options;
if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) {
  options = [[MLKAutoMLImageLabelerOptions alloc] initWithRemoteModel:remoteModel];
} else {
  options = [[MLKAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
}
options.confidenceThreshold = @(0.0);  // Evaluate your model in the Firebase console
                                       // to determine an appropriate value.
MLKImageLabeler *imageLabeler =
    [MLKImageLabeler imageLabelerWithOptions:options];

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

Вы можете получить статус загрузки модели, присоединив наблюдателей к Центру уведомлений по умолчанию. Обязательно используйте слабую ссылку на self в блоке наблюдателя, поскольку загрузка может занять некоторое время, а исходный объект может быть освобожден к моменту завершения загрузки. Например:

Быстрый

NotificationCenter.default.addObserver(
    forName: .mlkitModelDownloadDidSucceed,
    object: nil,
    queue: nil
) { [weak self] notification in
    guard let strongSelf = self,
        let userInfo = notification.userInfo,
        let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue]
            as? RemoteModel,
        model.name == "your_remote_model"
        else { return }
    // The model was downloaded and is available on the device
}

NotificationCenter.default.addObserver(
    forName: .mlkitModelDownloadDidFail,
    object: nil,
    queue: nil
) { [weak self] notification in
    guard let strongSelf = self,
        let userInfo = notification.userInfo,
        let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue]
            as? RemoteModel
        else { return }
    let error = userInfo[ModelDownloadUserInfoKey.error.rawValue]
    // ...
}

Цель-C

__weak typeof(self) weakSelf = self;

[NSNotificationCenter.defaultCenter
    addObserverForName:MLKModelDownloadDidSucceedNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

              MLKRemoteModel *model = note.userInfo[MLKModelDownloadUserInfoKeyRemoteModel];
              if ([model.name isEqualToString:@"your_remote_model"]) {
                // The model was downloaded and is available on the device
              }
            }];

[NSNotificationCenter.defaultCenter
    addObserverForName:MLKModelDownloadDidFailNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

              NSError *error = note.userInfo[MLKModelDownloadUserInfoKeyError];
            }];

2. Подготовьте входное изображение

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

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

  • Создайте объект VisionImage с помощью UIImage . Обязательно укажите правильную .orientation .

    Быстрый

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

    Цель-C

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

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

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

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

    Быстрый

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

    Цель-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 и ориентацию:

    Быстрый

    let image = VisionImage(buffer: sampleBuffer)
    image.orientation = imageOrientation(
      deviceOrientation: UIDevice.current.orientation,
      cameraPosition: cameraPosition)

    Цель-C

     MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
     image.orientation =
       [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                    cameraPosition:cameraPosition];

3. Запустите программу разметки изображений.

Асинхронно:

Быстрый

imageLabeler.process(image) { labels, error in
    guard error == nil, let labels = labels, !labels.isEmpty else {
        // Handle the error.
        return
    }
    // Show results.
}

Цель-C

[imageLabeler
    processImage:image
      completion:^(NSArray *_Nullable labels,
                   NSError *_Nullable error) {
        if (labels.count == 0) {
            // Handle the error.
            return;
        }
        // Show results.
     }];

Синхронно:

Быстрый

var labels: [ImageLabel]
do {
    labels = try imageLabeler.results(in: image)
} catch let error {
    // Handle the error.
    return
}
// Show results.

Цель-C

NSError *error;
NSArray *labels =
    [imageLabeler resultsInImage:image error:&error];
// Show results or handle the error.

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

Если операция маркировки изображения прошла успешно, она возвращает массив ImageLabel . Каждая ImageLabel представляет собой что-то, что было помечено на изображении. Вы можете получить текстовое описание каждой метки (если оно доступно в метаданных файла модели TensorFlow Lite), оценку достоверности и индекс. Например:

Быстрый

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

Цель-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 , чтобы синхронно получить результаты из данного видеокадра. Оставьте для AVCaptureVideoDataOutput значение alwaysDiscardsLateVideoFrames как true , чтобы ограничить вызовы детектора. Если во время работы детектора появится новый видеокадр, он будет удален.
  • Если вы используете выходные данные детектора для наложения графики на входное изображение, сначала получите результат из ML Kit, затем визуализируйте изображение и наложите его за один шаг. При этом вы выполняете рендеринг на поверхность дисплея только один раз для каждого обработанного входного кадра. Пример см. в updatePreviewOverlayViewWithLastFrame в образце быстрого запуска ML Kit.