Руководство по классификации изображений для iOS

Задача «Классификатор изображений» позволяет выполнять классификацию изображений. Эту задачу можно использовать, чтобы определить, что представляет собой изображение среди набора категорий, определенных во время обучения. В этих инструкциях показано, как использовать классификатор изображений в приложениях iOS. Пример кода, описанный в этой инструкции, доступен на GitHub .

Вы можете увидеть эту задачу в действии, просмотрев эту веб-демо . Дополнительные сведения о возможностях, моделях и параметрах конфигурации этой задачи см. в разделе Обзор .

Пример кода

Пример кода задач MediaPipe — это базовая реализация приложения классификатора изображений для iOS. В примере используется камера на физическом устройстве iOS для непрерывной классификации объектов, а также могут использоваться изображения и видео из галереи устройства для статической классификации объектов.

Вы можете использовать это приложение в качестве отправной точки для своего собственного приложения для iOS или обращаться к нему при изменении существующего приложения. Пример кода классификатора изображений размещен на GitHub .

Загрузите код

Следующие инструкции показывают, как создать локальную копию кода примера с помощью инструмента командной строки git .

Чтобы загрузить пример кода:

  1. Клонируйте репозиторий git, используя следующую команду:

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. При желании настройте свой экземпляр git на использование разреженной проверки, чтобы у вас были только файлы для примера приложения классификатора изображений:

    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_classification/ios/
    

После создания локальной версии примера кода вы можете установить библиотеку задач MediaPipe, открыть проект с помощью Xcode и запустить приложение. Инструкции см. в Руководстве по установке для iOS .

Ключевые компоненты

Следующие файлы содержат ключевой код для примера приложения классификатора изображений:

  • ImageClassifierService.swift : инициализирует классификатор изображений, обрабатывает выбор модели и выполняет вывод на входных данных.
  • CameraViewController.swift : реализует пользовательский интерфейс для режима ввода изображения с камеры в реальном времени и визуализирует результаты.
  • MediaLibraryViewController.swift Реализует пользовательский интерфейс для режима ввода неподвижных изображений и видеофайлов и визуализирует результаты.

Настраивать

В этом разделе описаны ключевые шаги по настройке среды разработки и проектов кода для использования Image Classifier. Общие сведения о настройке среды разработки для использования задач MediaPipe, включая требования к версии платформы, см. в руководстве по настройке для iOS .

Зависимости

Классификатор изображений использует библиотеку MediaPipeTasksVision , которую необходимо установить с помощью CocoaPods. Библиотека совместима с приложениями Swift и Objective-C и не требует дополнительной настройки для конкретного языка.

Инструкции по установке CocoaPods на macOS см. в руководстве по установке CocoaPods . Инструкции о том, как создать Podfile с необходимыми модулями для вашего приложения, см. в разделе Использование CocoaPods .

Добавьте модуль MediaPipeTasksVision в Podfile используя следующий код:

target 'MyImageClassifierApp' do
  use_frameworks!
  pod 'MediaPipeTasksVision'
end

Если ваше приложение включает в себя цели модульного тестирования, обратитесь к Руководству по настройке для iOS для получения дополнительной информации о настройке вашего Podfile .

Модель

Для задачи классификатора изображений MediaPipe требуется обученная модель, совместимая с этой задачей. Дополнительную информацию о доступных обученных моделях для Классификатора изображений см. в разделе «Модели» обзора задач.

Выберите и загрузите модель и добавьте ее в каталог проекта с помощью Xcode. Инструкции по добавлению файлов в проект Xcode см. в разделе Управление файлами и папками в проекте Xcode .

Используйте свойство BaseOptions.modelAssetPath , чтобы указать путь к модели в вашем пакете приложений. Пример кода см. в следующем разделе.

Создать задачу

Вы можете создать задачу «Классификатор изображений», вызвав один из ее инициализаторов. Инициализатор ImageClassifier(options:) устанавливает значения для параметров конфигурации, включая режим работы, локаль отображаемых имен, максимальное количество результатов, порог уверенности, список разрешенных категорий и список запрещенных.

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

Задача «Классификатор изображений» поддерживает три типа входных данных: неподвижные изображения, видеофайлы и прямые видеопотоки. По умолчанию ImageClassifier(modelPath:) инициализирует задачу для неподвижных изображений. Если вы хотите, чтобы ваша задача была инициализирована для обработки видеофайлов или прямых видеопотоков, используйте ImageClassifier(options:) , чтобы указать режим работы видео или прямой трансляции. Для режима прямой трансляции также требуется дополнительный параметр конфигурации imageClassifierLiveStreamDelegate , который позволяет классификатору изображений доставлять результаты классификации изображений делегату асинхронно.

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

Быстрый

Изображение

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ImageClassifierOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.maxResults = 5

let imageClassifier = try ImageClassifier(options: options)
    

Видео

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ImageClassifierOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.maxResults = 5

let imageClassifier = try ImageClassifier(options: options)
    

Прямая трансляция

import MediaPipeTasksVision

// Class that conforms to the `ImageClassifierLiveStreamDelegate` protocol and
// implements the method that the image classifier calls once it
// finishes performing classification on each input frame.
class ImageClassifierResultProcessor: NSObject, ImageClassifierLiveStreamDelegate {

   func imageClassifier(
    _ imageClassifier: ImageClassifier,
    didFinishClassification result: ImageClassifierResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the image classifier result or errors here.

  }
}

let modelPath = Bundle.main.path(
  forResource: "model",
  ofType: "tflite")

let options = ImageClassifierOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.maxResults = 5

// Assign an object of the class to the `imageClassifierLiveStreamDelegate`
// property.
let processor = ImageClassifierResultProcessor()
options.imageClassifierLiveStreamDelegate = processor

let imageClassifier = try ImageClassifier(options: options)
    

Цель-C

Изображение

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageClassifierOptions *options = [[MPPImageClassifierOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.maxResults = 5;

MPPImageClassifier *imageClassifier =
      [[MPPImageClassifier alloc] initWithOptions:options error:nil];
    

Видео

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageClassifierOptions *options = [[MPPImageClassifierOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.maxResults = 5;

MPPImageClassifier *imageClassifier =
      [[MPPImageClassifier alloc] initWithOptions:options error:nil];
    

Прямая трансляция

@import MediaPipeTasksVision;

// Class that conforms to the `MPPImageClassifierLiveStreamDelegate` protocol
// and implements the method that the image classifier calls once it finishes
// performing classification on each input frame.

@interface APPImageClassifierResultProcessor : NSObject 

@end

@implementation APPImageClassifierResultProcessor

-   (void)imageClassifier:(MPPImageClassifier *)imageClassifier
    didFinishClassificationWithResult:(MPPImageClassifierResult *)imageClassifierResult
              timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                                error:(NSError *)error {

    // Process the image classifier result or errors here.

}

@end

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageClassifierOptions *options = [[MPPImageClassifierOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.maxResults = 5;

// Assign an object of the class to the `imageClassifierLiveStreamDelegate`
// property.
APPImageClassifierResultProcessor *processor = [APPImageClassifierResultProcessor new];
options.imageClassifierLiveStreamDelegate = processor;

MPPImageClassifier *imageClassifier =
      [[MPPImageClassifier alloc] initWithOptions:options error:nil];
    

Варианты конфигурации

Эта задача имеет следующие параметры конфигурации для приложений iOS:

Название опции Описание Диапазон значений Значение по умолчанию
runningMode Устанавливает режим выполнения задачи. Есть три режима:

ИЗОБРАЖЕНИЕ: Режим для ввода одного изображения.

ВИДЕО: Режим декодированных кадров видео.

LIVE_STREAM: режим прямой трансляции входных данных, например с камеры. В этом режиме необходимо вызвать resultListener, чтобы настроить прослушиватель на асинхронное получение результатов.
{ RunningMode.image, RunningMode.video, RunningMode.liveStream } RunningMode.image
displayNamesLocale Задает язык меток, которые будут использоваться для отображаемых имен, представленных в метаданных модели задачи, если они доступны. По умолчанию en английский язык. Вы можете добавить локализованные метки к метаданным пользовательской модели с помощью API записи метаданных TensorFlow Lite. Код региона ru
maxResults Устанавливает необязательное максимальное количество возвращаемых результатов классификации с наивысшим баллом. Если < 0, будут возвращены все доступные результаты. Любые положительные числа -1
scoreThreshold Устанавливает порог оценки прогноза, который переопределяет тот, который указан в метаданных модели (если таковые имеются). Результаты ниже этого значения отклоняются. Любой плавающий Не установлено
categoryAllowlist Устанавливает необязательный список разрешенных имен категорий. Если поле не пусто, результаты классификации, имя категории которых отсутствует в этом наборе, будут отфильтрованы. Повторяющиеся или неизвестные названия категорий игнорируются. Эта опция является взаимоисключающей с categoryDenylist , и использование обеих приводит к ошибке. Любые строки Не установлено
categoryDenylist Устанавливает необязательный список имен категорий, которые не разрешены. Если значение не пустое, результаты классификации, имя категории которых находится в этом наборе, будут отфильтрованы. Повторяющиеся или неизвестные названия категорий игнорируются. Эта опция является взаимоисключающей с categoryAllowlist , и использование обеих приводит к ошибке. Любые строки Не установлено
resultListener Настраивает прослушиватель результатов на асинхронное получение результатов классификации, когда классификатор изображений находится в режиме прямого потока. Может использоваться только в том случае, если для режима работы установлено значение LIVE_STREAM Н/Д Не установлено

Конфигурация прямой трансляции

Если в качестве рабочего режима установлена ​​прямая трансляция, классификатору изображений требуется дополнительный параметр конфигурации imageClassifierLiveStreamDelegate , который позволяет классификатору доставлять результаты классификации асинхронно. Делегат реализует метод imageClassifier(_:didFinishClassification:timestampInMilliseconds:error:) , который вызывается классификатором изображений после обработки результатов классификации для каждого кадра.

Название опции Описание Диапазон значений Значение по умолчанию
imageClassifierLiveStreamDelegate Позволяет классификатору изображений асинхронно получать результаты классификации в режиме прямой трансляции. Класс, экземпляру которого присвоено это свойство, должен реализовать метод imageClassifier(_:didFinishClassification:timestampInMilliseconds:error:) . Непригодный Не установлено

Подготовьте данные

Вам необходимо преобразовать входное изображение или кадр в объект MPImage перед передачей его в классификатор изображений. MPImage поддерживает различные типы форматов изображений iOS и может использовать их в любом рабочем режиме для вывода. Для получения дополнительной информации о MPImage обратитесь к MPImage API .

Выберите формат изображения iOS в зависимости от вашего варианта использования и режима работы, который требуется вашему приложению. MPImage принимает форматы изображений iOS UIImage , CVPixelBuffer и CMSampleBuffer .

UIImage

Формат UIImage хорошо подходит для следующих режимов работы:

  • Изображения: изображения из пакета приложения, пользовательской галереи или файловой системы, отформатированные как изображения UIImage можно преобразовать в объект MPImage .

  • Видео: используйте AVAssetImageGenerator для извлечения видеокадров в формат CGImage , а затем преобразуйте их в изображения UIImage .

Быстрый

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(uiImage: image)
    

Цель-C

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

В примере инициализируется MPImage с ориентацией UIImage.Orientation.Up по умолчанию. Вы можете инициализировать MPImage любым из поддерживаемых значений UIImage.Orientation . Классификатор изображений не поддерживает зеркальные ориентации, такие как .upMirrored , .downMirrored , .leftMirrored , .rightMirrored .

Для получения дополнительной информации о UIImage обратитесь к документации UIImage Apple Developer Documentation .

CVPixelBuffer

Формат CVPixelBuffer хорошо подходит для приложений, генерирующих кадры и использующих для обработки платформу iOS CoreImage .

Формат CVPixelBuffer хорошо подходит для следующих режимов работы:

  • Изображения: приложения, которые генерируют изображения CVPixelBuffer после некоторой обработки с использованием платформы iOS CoreImage могут быть отправлены в классификатор изображений в режиме работы изображения.

  • Видео: видеокадры можно конвертировать в формат CVPixelBuffer для обработки, а затем отправлять в классификатор изображений в режиме видео.

  • прямая трансляция: приложения, использующие камеру iOS для создания кадров, могут быть преобразованы в формат CVPixelBuffer для обработки перед отправкой в ​​классификатор изображений в режиме прямой трансляции.

Быстрый

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(pixelBuffer: pixelBuffer)
    

Цель-C

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

Дополнительные сведения о CVPixelBuffer см. в документации разработчика Apple CVPixelBuffer .

CMSampleBuffer

Формат CMSampleBuffer хранит образцы мультимедиа единого типа и хорошо подходит для режима прямой трансляции. Кадры в реальном времени с камер iOS асинхронно доставляются в формате CMSampleBuffer с помощью iOS AVCaptureVideoDataOutput .

Быстрый

// Obtain a CMSampleBuffer.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(sampleBuffer: sampleBuffer)
    

Цель-C

// Obtain a `CMSampleBuffer`.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
    

Дополнительные сведения о CMSampleBuffer см. в документации CMSampleBuffer Apple для разработчиков .

Запустить задачу

Чтобы запустить классификатор изображений, используйте метод classify() специфичный для назначенного режима работы:

  • Неподвижное изображение: classify(image:)
  • Видео: classify(videoFrame:timestampInMilliseconds:)
  • прямая трансляция: classifyAsync(image:timestampInMilliseconds:)

Классификатор изображений возвращает возможные категории объекта во входном изображении или кадре.

В следующих примерах кода показаны основные примеры запуска Image Classifier в различных режимах работы:

Быстрый

Изображение

let result = try imageClassifier.classify(image: image)
    

Видео

let result = try imageClassifier.classify(
  videoFrame: image,
  timestampInMilliseconds: timestamp)
    

Прямая трансляция

try imageClassifier.classifyAsync(
  image: image,
  timestampInMilliseconds: timestamp)
    

Цель-C

Изображение

MPPImageClassifierResult *result = [imageClassifier classifyImage:image
                                                            error:nil];
    

Видео

MPPImageClassifierResult *result = [imageClassifier classifyVideoFrame:image
                                               timestampInMilliseconds:timestamp
                                                                 error:nil];
    

Прямая трансляция

BOOL success = [imageClassifier classifyAsyncImage:image
                          timestampInMilliseconds:timestamp
                                            error:nil];
    

В примере кода классификатора изображений более подробно показаны реализации каждого из этих режимов classify(image:) , classify(videoFrame:timestampInMilliseconds:) и classifyAsync(image:timestampInMilliseconds:) . Пример кода позволяет пользователю переключаться между режимами обработки, которые могут не потребоваться для вашего варианта использования.

Обратите внимание на следующее:

  • При работе в режиме видео или в режиме прямой трансляции вы также должны предоставить метку времени входного кадра задаче классификатора изображений.

  • При работе в режиме изображения или видео задача «Классификатор изображений» блокирует текущий поток до тех пор, пока не завершит обработку входного изображения или кадра. Чтобы избежать блокировки текущего потока, выполните обработку в фоновом потоке с помощью платформ iOS Dispatch или NSOperation .

  • При работе в режиме прямой трансляции задача классификатора изображений немедленно возвращается и не блокирует текущий поток. Он вызывает метод imageClassifier(_:didFinishClassification:timestampInMilliseconds:error:) с результатом классификации после обработки каждого входного кадра. Классификатор изображений вызывает этот метод асинхронно в выделенной последовательной очереди отправки. Для отображения результатов в пользовательском интерфейсе отправьте результаты в основную очередь после обработки результатов. Если функция classifyAsync вызывается, когда задача классификатора изображений занята обработкой другого кадра, классификатор изображений игнорирует новый входной кадр.

Обработка и отображение результатов

После выполнения вывода задача «Классификатор изображений» возвращает объект ImageClassifierResult , который содержит список возможных категорий для объектов во входном изображении или кадре.

Ниже показан пример выходных данных этой задачи:

ImageClassifierResult:
 Classifications #0 (single classification head):
  head index: 0
  category #0:
   category name: "/m/01bwb9"
   display name: "Passer domesticus"
   score: 0.91406
   index: 671
  category #1:
   category name: "/m/01bwbt"
   display name: "Passer montanus"
   score: 0.00391
   index: 670

Этот результат был получен путем запуска Классификатора птиц на:

Пример кода классификатора изображений демонстрирует, как отображать результаты классификации, возвращенные из задачи. Подробности см. в примере кода .