Руководство по обнаружению объектов для iOS

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

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

Пример кода

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

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

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

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

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

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

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

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

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

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

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

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

Настраивать

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

Зависимости

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

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

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

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

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

Модель

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

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

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

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

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

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

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

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

Быстрый

Изображение

import MediaPipeTasksVision

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

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

let objectDetector = try ObjectDetector(options: options)
    

Видео

import MediaPipeTasksVision

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

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

let objectDetector = try ObjectDetector(options: options)
    

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

import MediaPipeTasksVision

// Class that conforms to the `ObjectDetectorLiveStreamDelegate` protocol and
// implements the method that the object detector calls once it
// finishes performing detection on each input frame.
class ObjectDetectorResultProcessor: NSObject, ObjectDetectorLiveStreamDelegate {

  func objectDetector(
    _ objectDetector: ObjectDetector,
    didFinishDetection objectDetectionResult: ObjectDetectorResult?,
    timestampInMilliseconds: Int,
    error: Error?) {
    // Process the detection result or errors here.
  }
}

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

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

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

let objectDetector = try ObjectDetector(options: options)
    

Цель-C

Изображение

@import MediaPipeTasksVision;

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

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

MPPObjectDetector *objectDetector =
      [[MPPObjectDetector alloc] initWithOptions:options error:nil];
    

Видео

@import MediaPipeTasksVision;

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

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

MPPObjectDetector *objectDetector =
      [[MPPObjectDetector alloc] initWithOptions:options error:nil];
    

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

@import MediaPipeTasksVision;

// Class that conforms to the `ObjectDetectorLiveStreamDelegate` protocol and
// implements the method that the object detector calls once it
// finishes performing detection on each input frame.

@interface APPObjectDetectorResultProcessor : NSObject 

@end

@implementation MPPObjectDetectorResultProcessor

-   (void)objectDetector:(MPPObjectDetector *)objectDetector
    didFinishDetectionWithResult:(MPPObjectDetectorResult *)ObjectDetectorResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the detection result or errors here.

}

@end

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

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

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

MPPObjectDetector *objectDetector =
      [[MPPObjectDetector alloc] initWithOptions:options error:nil];
    

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

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

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

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

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

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

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

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

Название опции Описание Диапазон значений Значение по умолчанию
objectDetectorLiveStreamDelegate Позволяет Object Detector получать результаты обнаружения асинхронно в режиме прямой трансляции. Класс, экземпляру которого присвоено это свойство, должен реализовать метод objectDetector(_:didFinishDetection: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 для разработчиков .

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

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

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

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

Быстрый

Изображение

let objectDetector.detect(image:image)
    

Видео

let objectDetector.detect(videoFrame:image)
    

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

let objectDetector.detectAsync(image:image)
    

Цель-C

Изображение

MPPObjectDetectorResult *result = [objectDetector detectInImage:image error:nil];
    

Видео

MPPObjectDetectorResult *result = [objectDetector detectInVideoFrame:image          timestampInMilliseconds:timestamp error:nil];
    

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

BOOL success = [objectDetector detectAsyncInImage:image
                          timestampInMilliseconds:timestamp
                                            error:nil];
    

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

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

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

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

  • При работе в режиме прямой трансляции задача «Детектор объектов» возвращается немедленно и не блокирует текущий поток. Он вызывает метод objectDetector(_objectDetector:didFinishDetection:timestampInMilliseconds:error:) с результатом обнаружения после обработки каждого входного кадра. Детектор объектов вызывает этот метод асинхронно в выделенной последовательной очереди отправки. Для отображения результатов в пользовательском интерфейсе отправьте результаты в основную очередь после обработки результатов. Если detectAsync вызывается, когда задача «Детектор объектов» занята обработкой другого кадра, Детектор объектов игнорирует новый входной кадр.

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

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

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

ObjectDetectorResult:
 Detection #0:
  Box: (x: 355, y: 133, w: 190, h: 206)
  Categories:
   index       : 17
   score       : 0.73828
   class name  : dog
 Detection #1:
  Box: (x: 103, y: 15, w: 138, h: 369)
  Categories:
   index       : 17
   score       : 0.73047
   class name  : dog

На следующем изображении показана визуализация результатов задачи:

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