Задача Pose Landmarker позволяет обнаруживать ориентиры человеческих тел на изображении или видео. Вы можете использовать это задание для определения ключевых положений тела, анализа позы и классификации движений. В этой задаче используются модели машинного обучения (ML), которые работают с отдельными изображениями или видео. Задача выводит ориентиры позы тела в координатах изображения и в трехмерных мировых координатах.
В этих инструкциях показано, как использовать Pose Landmarker с приложениями для iOS. Пример кода, описанный в этой инструкции, доступен на GitHub .
Вы можете увидеть эту задачу в действии, просмотрев эту веб-демо . Дополнительные сведения о возможностях, моделях и параметрах конфигурации этой задачи см. в разделе Обзор .
Пример кода
Пример кода задач MediaPipe — это базовая реализация приложения Pose Landmarker для iOS. В примере используется камера на физическом устройстве iOS для обнаружения поз в непрерывном видеопотоке. Приложение также может определять позы на изображениях и видео из галереи устройства.
Вы можете использовать это приложение в качестве отправной точки для своего собственного приложения для iOS или обращаться к нему при изменении существующего приложения. Пример кода Pose Landmarker размещен на GitHub .
Загрузите код
Следующие инструкции показывают, как создать локальную копию кода примера с помощью инструмента командной строки git .
Чтобы загрузить пример кода:
Клонируйте репозиторий git, используя следующую команду:
git clone https://github.com/google-ai-edge/mediapipe-samples
При желании настройте свой экземпляр git на использование разреженной проверки, чтобы у вас были только файлы для примера приложения Pose Landmarker:
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/pose_landmarker/ios/
После создания локальной версии примера кода вы можете установить библиотеку задач MediaPipe, открыть проект с помощью Xcode и запустить приложение. Инструкции см. в Руководстве по установке для iOS .
Ключевые компоненты
Следующие файлы содержат ключевой код для примера приложения Pose Landmarker:
- PoseLandmarkerService.swift : инициализирует ориентир, обрабатывает выбор модели и выполняет вывод на основе входных данных.
- CameraViewController : реализует пользовательский интерфейс для режима ввода изображения с камеры в реальном времени и визуализирует ориентиры.
- MediaLibraryViewController.swift : реализует пользовательский интерфейс для режима ввода неподвижных изображений и видеофайлов и визуализирует ориентиры.
Настраивать
В этом разделе описаны ключевые шаги по настройке среды разработки и проектов кода для использования Pose Landmarker. Общие сведения о настройке среды разработки для использования задач MediaPipe, включая требования к версии платформы, см. в руководстве по настройке для iOS .
Зависимости
Pose Landmarker использует библиотеку MediaPipeTasksVision
, которую необходимо установить с помощью CocoaPods. Библиотека совместима с приложениями Swift и Objective-C и не требует дополнительной настройки для конкретного языка.
Инструкции по установке CocoaPods на macOS см. в руководстве по установке CocoaPods . Инструкции о том, как создать Podfile
с необходимыми модулями для вашего приложения, см. в разделе Использование CocoaPods .
Добавьте модуль MediaPipeTasksVision в Podfile
используя следующий код:
target 'MyPoseLandmarkerApp' do
use_frameworks!
pod 'MediaPipeTasksVision'
end
Если ваше приложение включает в себя цели модульного тестирования, обратитесь к Руководству по настройке для iOS для получения дополнительной информации о настройке вашего Podfile
.
Модель
Для задачи MediaPipe Pose Landmarker требуется обученный пакет, совместимый с этой задачей. Дополнительную информацию о доступных обученных моделях для Pose Landmarker см. в разделе «Модели» обзора задач.
Используйте сценарий download_models.sh
, чтобы загрузить модели и добавить их в каталог проекта с помощью Xcode. Инструкции по добавлению файлов в проект Xcode см. в разделе Управление файлами и папками в проекте Xcode .
Используйте свойство BaseOptions.modelAssetPath
, чтобы указать путь к модели в вашем пакете приложений. Пример кода см. в следующем разделе.
Создать задачу
Вы можете создать задачу Pose Landmarker, вызвав один из ее инициализаторов. Инициализатор PoseLandmarker(options:)
принимает значения для параметров конфигурации.
Если вам не нужен ориентир Pose Landmarker, инициализированный с настраиваемыми параметрами конфигурации, вы можете использовать инициализатор PoseLandmarker(modelPath:)
для создания ориентира Pose с параметрами по умолчанию. Дополнительные сведения о параметрах конфигурации см. в разделе Обзор конфигурации .
Задача Pose Landmarker поддерживает 3 типа входных данных: неподвижные изображения, видеофайлы и прямые видеопотоки. По умолчанию PoseLandmarker(modelPath:)
инициализирует задачу для неподвижных изображений. Если вы хотите, чтобы ваша задача была инициализирована для обработки видеофайлов или прямых видеопотоков, используйте PoseLandmarker(options:)
, чтобы указать режим работы видео или прямой трансляции. Для режима прямой трансляции также требуется дополнительный параметр poseLandmarkerLiveStreamDelegate
, который позволяет Pose Landmarker асинхронно доставлять делегату результаты обнаружения ориентиров позы.
Выберите вкладку, соответствующую вашему режиму работы, чтобы узнать, как создать задачу и выполнить вывод.
Быстрый
Изображение
import MediaPipeTasksVision let modelPath = Bundle.main.path(forResource: "pose_landmarker", ofType: "task") let options = PoseLandmarkerOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .image options.minPoseDetectionConfidence = minPoseDetectionConfidence options.minPosePresenceConfidence = minPosePresenceConfidence options.minTrackingConfidence = minTrackingConfidence options.numPoses = numPoses let poseLandmarker = try PoseLandmarker(options: options)
Видео
import MediaPipeTasksVision let modelPath = Bundle.main.path(forResource: "pose_landmarker", ofType: "task") let options = PoseLandmarkerOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .video options.minPoseDetectionConfidence = minPoseDetectionConfidence options.minPosePresenceConfidence = minPosePresenceConfidence options.minTrackingConfidence = minTrackingConfidence options.numPoses = numPoses let poseLandmarker = try PoseLandmarker(options: options)
Прямая трансляция
import MediaPipeTasksVision // Class that conforms to the `PoseLandmarkerLiveStreamDelegate` protocol and // implements the method that the pose landmarker calls once it finishes // performing pose landmark detection in each input frame. class PoseLandmarkerResultProcessor: NSObject, PoseLandmarkerLiveStreamDelegate { func poseLandmarker( _ poseLandmarker: PoseLandmarker, didFinishDetection result: PoseLandmarkerResult?, timestampInMilliseconds: Int, error: Error?) { // Process the pose landmarker result or errors here. } } let modelPath = Bundle.main.path(forResource: "pose_landmarker", ofType: "task") let options = PoseLandmarkerOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .liveStream options.minPoseDetectionConfidence = minPoseDetectionConfidence options.minPosePresenceConfidence = minPosePresenceConfidence options.minTrackingConfidence = minTrackingConfidence options.numPoses = numPoses // Assign an object of the class to the `poseLandmarkerLiveStreamDelegate` // property. let processor = PoseLandmarkerResultProcessor() options.poseLandmarkerLiveStreamDelegate = processor let poseLandmarker = try PoseLandmarker(options: options)
Цель-C
Изображение
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"pose_landmarker" ofType:@"task"]; MPPPoseLandmarkerOptions *options = [[MPPPoseLandmarkerOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeImage; options.minPoseDetectionConfidence = minPoseDetectionConfidence; options.minPosePresenceConfidence = minPosePresenceConfidence; options.minTrackingConfidence = minTrackingConfidence; options.numPoses = numPoses; MPPPoseLandmarker *poseLandmarker = [[MPPPoseLandmarker alloc] initWithOptions:options error:nil];
Видео
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"pose_landmarker" ofType:@"task"]; MPPPoseLandmarkerOptions *options = [[MPPPoseLandmarkerOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeVideo; options.minPoseDetectionConfidence = minPoseDetectionConfidence; options.minPosePresenceConfidence = minPosePresenceConfidence; options.minTrackingConfidence = minTrackingConfidence; options.numPoses = numPoses; MPPPoseLandmarker *poseLandmarker = [[MPPPoseLandmarker alloc] initWithOptions:options error:nil];
Прямая трансляция
@import MediaPipeTasksVision; // Class that conforms to the `MPPPoseLandmarkerLiveStreamDelegate` protocol // and implements the method that the pose landmarker calls once it finishes // performing pose landmarks= detection in each input frame. @interface APPPoseLandmarkerResultProcessor : NSObject@end @implementation APPPoseLandmarkerResultProcessor - (void)poseLandmarker:(MPPPoseLandmarker *)poseLandmarker didFinishDetectionWithResult:(MPPPoseLandmarkerResult *)poseLandmarkerResult timestampInMilliseconds:(NSInteger)timestampInMilliseconds error:(NSError *)error { // Process the pose landmarker result or errors here. } @end NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"pose_landmarker" ofType:@"task"]; MPPPoseLandmarkerOptions *options = [[MPPPoseLandmarkerOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeLiveStream; options.minPoseDetectionConfidence = minPoseDetectionConfidence; options.minPosePresenceConfidence = minPosePresenceConfidence; options.minTrackingConfidence = minTrackingConfidence; options.numPoses = numPoses; // Assign an object of the class to the `poseLandmarkerLiveStreamDelegate` // property. APPPoseLandmarkerResultProcessor *processor = [APPPoseLandmarkerResultProcessor new]; options.poseLandmarkerLiveStreamDelegate = processor; MPPPoseLandmarker *poseLandmarker = [[MPPPoseLandmarker alloc] initWithOptions:options error:nil];
Примечание. Если вы используете режим видео или режим прямой трансляции, Pose Landmarker использует отслеживание, чтобы избежать запуска модели обнаружения ладоней в каждом кадре, что помогает уменьшить задержку.
Варианты конфигурации
Эта задача имеет следующие параметры конфигурации для приложений iOS:
Название опции | Описание | Диапазон значений | Значение по умолчанию |
---|---|---|---|
running_mode | Устанавливает режим выполнения задачи. Есть три режима: ИЗОБРАЖЕНИЕ: Режим для ввода одного изображения. ВИДЕО: Режим декодированных кадров видео. LIVE_STREAM: режим прямой трансляции входных данных, например с камеры. В этом режиме poseLandmarkerLiveStreamDelegate необходимо задать экземпляр класса, который реализует PoseLandmarkerLiveStreamDelegate , чтобы получать результаты асинхронного обнаружения ориентиров позы. | { RunningMode.image, RunningMode.video, RunningMode.liveStream } | RunningMode.image |
num_poses | Максимальное количество поз, которые может обнаружить ориентир позы. | Integer > 0 | 1 |
min_pose_detection_confidence | Минимальный показатель достоверности, позволяющий считать обнаружение позы успешным. | Float [0.0,1.0] | 0.5 |
min_pose_presence_confidence | Минимальный показатель достоверности оценки присутствия позы при обнаружении ориентира позы. | Float [0.0,1.0] | 0.5 |
min_tracking_confidence | Минимальный показатель достоверности, позволяющий отслеживанию позы считаться успешным. | Float [0.0,1.0] | 0.5 |
output_segmentation_masks | Выводит ли Pose Landmarker маску сегментации для обнаруженной позы. | Boolean | False |
result_callback | Настраивает прослушиватель результатов на асинхронное получение результатов ориентира, когда Pose Landmarker находится в режиме прямой трансляции. Может использоваться только в том случае, если для режима работы установлено значение LIVE_STREAM | ResultListener | N/A |
Конфигурация прямой трансляции
Когда режим бега установлен на прямую трансляцию, для Pose Landmarker требуется дополнительный параметр poseLandmarkerLiveStreamDelegate
, который позволяет Pose Landmarker асинхронно доставлять результаты обнаружения ориентиров позы. Делегат должен реализовать poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:)
, который вызывается Pose Landmarker после обработки результатов обнаружения ориентиров позы в каждом кадре.
Название опции | Описание | Диапазон значений | Значение по умолчанию |
---|---|---|---|
poseLandmarkerLiveStreamDelegate | Позволяет Pose Landmarker получать результаты асинхронного обнаружения ориентиров позы в режиме прямой трансляции. Класс, экземпляру которого присвоено это свойство, должен реализовать poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) . | Непригодный | Не установлено |
Подготовьте данные
Вам необходимо преобразовать входное изображение или кадр в объект MPImage
, прежде чем передавать его в Pose Landmarker. 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 . Pose Landmarker не поддерживает зеркальные ориентации, такие как .upMirrored
, .downMirrored
, .leftMirrored
, .rightMirrored
.
Для получения дополнительной информации о UIImage
обратитесь к документации UIImage Apple Developer Documentation .
CVPixelBuffer
Формат CVPixelBuffer
хорошо подходит для приложений, генерирующих кадры и использующих для обработки платформу iOS CoreImage .
Формат CVPixelBuffer
хорошо подходит для следующих режимов работы:
Изображения: приложения, которые генерируют изображения
CVPixelBuffer
после некоторой обработки с использованием платформы iOSCoreImage
, могут быть отправлены в Pose Landmarker в режиме работы изображения.Видео: видеокадры можно конвертировать в формат
CVPixelBuffer
для обработки, а затем отправлять в Pose Landmarker в видеорежиме.прямая трансляция: приложения, использующие камеру iOS для создания кадров, могут быть преобразованы в формат
CVPixelBuffer
для обработки перед отправкой в Pose Landmarker в режиме прямой трансляции.
Быстрый
// 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:timestampInMilliseconds:)
В следующих примерах кода показаны простые примеры запуска Pose Landmarker в различных режимах работы:
Быстрый
Изображение
let result = try poseLandmarker.detect(image: image)
Видео
let result = try poseLandmarker.detect( videoFrame: image, timestampInMilliseconds: timestamp)
Прямая трансляция
try poseLandmarker.detectAsync( image: image, timestampInMilliseconds: timestamp)
Цель-C
Изображение
MPPPoseLandmarkerResult *result = [poseLandmarker detectImage:image error:nil];
Видео
MPPPoseLandmarkerResult *result = [poseLandmarker detectVideoFrame:image timestampInMilliseconds:timestamp error:nil];
Прямая трансляция
BOOL success = [poseLandmarker detectAsyncImage:image timestampInMilliseconds:timestamp error:nil];
В примере кода Pose Landmarker более detect(image:)
показаны реализации каждого из detectAsync(image:timestampInMilliseconds:)
режимов detect(videoFrame:timestampInMilliseconds:)
Пример кода позволяет пользователю переключаться между режимами обработки, которые могут не потребоваться для вашего варианта использования.
Обратите внимание на следующее:
При работе в режиме видео или в режиме прямой трансляции вы также должны предоставить метку времени входного кадра для задачи Pose Landmarker.
При работе в режиме изображения или видео задача Pose Landmarker блокирует текущий поток до тех пор, пока не завершит обработку входного изображения или кадра. Чтобы избежать блокировки текущего потока, выполните обработку в фоновом потоке с помощью платформ iOS Dispatch или NSOperation .
При работе в режиме прямой трансляции задача Pose Landmarker немедленно возвращается и не блокирует текущий поток. Он вызывает
poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:)
с результатом определения ориентира позы после обработки каждого входного кадра. Pose Landmarker вызывает этот метод асинхронно в выделенной последовательной очереди отправки. Для отображения результатов в пользовательском интерфейсе отправьте результаты в основную очередь после обработки результатов. Если функцияdetectAsync
вызывается, когда задача Pose Landmarker занята обработкой другого кадра, Pose Landmarker игнорирует новый входной кадр.
Обработка и отображение результатов
После выполнения вывода задача Pose Landmarker возвращает PoseLandmarkerResult
, который содержит координаты для каждого ориентира позы.
Ниже показан пример выходных данных этой задачи:
PoseLandmarkerResult:
Landmarks:
Landmark #0:
x : 0.638852
y : 0.671197
z : 0.129959
visibility : 0.9999997615814209
presence : 0.9999984502792358
Landmark #1:
x : 0.634599
y : 0.536441
z : -0.06984
visibility : 0.999909
presence : 0.999958
... (33 landmarks per pose)
WorldLandmarks:
Landmark #0:
x : 0.067485
y : 0.031084
z : 0.055223
visibility : 0.9999997615814209
presence : 0.9999984502792358
Landmark #1:
x : 0.063209
y : -0.00382
z : 0.020920
visibility : 0.999976
presence : 0.999998
... (33 world landmarks per pose)
SegmentationMasks:
... (pictured below)
Выходные данные содержат как нормализованные координаты ( Landmarks
), так и мировые координаты ( WorldLandmarks
) для каждого ориентира.
Выходные данные содержат следующие нормализованные координаты ( Landmarks
):
x
иy
: координаты ориентира, нормированные между 0,0 и 1,0 по ширине изображения (x
) и высоте (y
).z
: Глубина ориентира, в качестве исходной точки используется глубина в середине бедер. Чем меньше значение, тем ближе ориентир к камере. Величина z использует примерно тот же масштаб, что иx
.visibility
: вероятность того, что ориентир будет виден на изображении.
Вывод содержит следующие мировые координаты ( WorldLandmarks
):
x
,y
иz
: Реальные трехмерные координаты в метрах, в качестве начала координат используется середина бедер.visibility
: вероятность того, что ориентир будет виден на изображении.
На следующем изображении показана визуализация результатов задачи:
Дополнительная маска сегментации представляет вероятность того, что каждый пиксель принадлежит обнаруженному человеку. Следующее изображение представляет собой маску сегментации выходных данных задачи:
Пример кода Pose Landmarker демонстрирует, как отображать результаты Pose Landmarker.