Задача «Распознаватель жестов MediaPipe» позволяет распознавать жесты рук в реальном времени и предоставляет результаты распознанных жестов рук и ориентиры обнаруженных рук. В этих инструкциях показано, как использовать Распознаватель жестов с приложениями iOS.
Вы можете увидеть эту задачу в действии, просмотрев веб-демо. Дополнительные сведения о возможностях, моделях и параметрах конфигурации этой задачи см. в разделе Обзор .
Пример кода
Пример кода задач MediaPipe — это базовая реализация приложения распознавания жестов для iOS. В примере используется камера на физическом устройстве iOS для постоянного обнаружения жестов рук, а также могут использоваться изображения и видео из галереи устройства для статического обнаружения жестов.
Вы можете использовать это приложение в качестве отправной точки для своего собственного приложения для iOS или обращаться к нему при изменении существующего приложения. Пример кода Распознавателя жестов размещен на GitHub .
Загрузите код
Следующие инструкции показывают, как создать локальную копию кода примера с помощью инструмента командной строки git .
Чтобы загрузить пример кода:
Клонируйте репозиторий git, используя следующую команду:
git clone https://github.com/google-ai-edge/mediapipe-samples
При желании настройте свой экземпляр git на использование разреженной проверки, чтобы у вас были только файлы для примера приложения Распознаватель жестов:
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/gesture_recognizer/ios/
После создания локальной версии примера кода вы можете установить библиотеку задач MediaPipe, открыть проект с помощью Xcode и запустить приложение. Инструкции см. в Руководстве по установке для iOS .
Ключевые компоненты
Следующие файлы содержат ключевой код для примера приложения Распознаватель жестов:
- GestureRecouncerService.swift : инициализирует Распознаватель жестов, обрабатывает выбор модели и выполняет логический вывод на входных данных.
- CameraViewController.swift : реализует пользовательский интерфейс для режима ввода изображения с камеры в реальном времени и визуализирует результаты.
- MediaLibraryViewController.swift : реализует пользовательский интерфейс для режима ввода неподвижных изображений и видеофайлов и визуализирует результаты.
Настраивать
В этом разделе описаны ключевые шаги по настройке среды разработки и проектов кода для использования Распознаватель жестов. Общие сведения о настройке среды разработки для использования задач MediaPipe, включая требования к версии платформы, см. в руководстве по настройке для iOS .
Зависимости
Распознаватель жестов использует библиотеку MediaPipeTasksVision
, которую необходимо установить с помощью CocoaPods. Библиотека совместима с приложениями Swift и Objective-C и не требует дополнительной настройки для конкретного языка.
Инструкции по установке CocoaPods на macOS см. в руководстве по установке CocoaPods . Инструкции о том, как создать Podfile
с необходимыми модулями для вашего приложения, см. в разделе Использование CocoaPods .
Добавьте модуль MediaPipeTasksVision в Podfile
используя следующий код:
target 'MyGestureRecognizerApp' do
use_frameworks!
pod 'MediaPipeTasksVision'
end
Если ваше приложение включает в себя цели модульного тестирования, обратитесь к Руководству по настройке для iOS для получения дополнительной информации о настройке вашего Podfile
.
Модель
Для задачи Распознавателя жестов MediaPipe требуется обученная модель, совместимая с этой задачей. Дополнительные сведения о доступных обученных моделях для Распознаватель жестов см. в разделе «Модели» обзора задач.
Выберите и загрузите модель и добавьте ее в каталог проекта с помощью Xcode. Инструкции по добавлению файлов в проект Xcode см. в разделе Управление файлами и папками в проекте Xcode .
Используйте свойство BaseOptions.modelAssetPath
, чтобы указать путь к модели в вашем пакете приложений. Пример кода см. в следующем разделе.
Создать задачу
Вы можете создать задачу «Распознаватель жестов», вызвав один из ее инициализаторов. Инициализатор GestureRecognizer(options:)
принимает значения для параметров конфигурации.
Если вам не нужен Распознаватель жестов, инициализированный с настраиваемыми параметрами конфигурации, вы можете использовать инициализатор GestureRecognizer(modelPath:)
для создания Распознаватель жестов с параметрами по умолчанию. Дополнительные сведения о параметрах конфигурации см. в разделе Обзор конфигурации .
Задача «Распознаватель жестов» поддерживает три типа входных данных: неподвижные изображения, видеофайлы и прямые видеопотоки. По умолчанию GestureRecognizer(modelPath:)
инициализирует задачу для неподвижных изображений. Если вы хотите, чтобы ваша задача была инициализирована для обработки видеофайлов или прямых видеопотоков, используйте GestureRecognizer(options:)
чтобы указать режим работы видео или прямой трансляции. Для режима прямой трансляции также требуется дополнительный параметр gestureRecognizerLiveStreamDelegate
, который позволяет распознавателю жестов асинхронно доставлять делегату результаты распознавания жестов.
Выберите вкладку, соответствующую вашему режиму работы, чтобы узнать, как создать задачу и выполнить вывод.
Быстрый
Изображение
import MediaPipeTasksVision let modelPath = Bundle.main.path(forResource: "gesture_recognizer", ofType: "task") let options = GestureRecognizerOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .image options.minHandDetectionConfidence = minHandDetectionConfidence options.minHandPresenceConfidence = minHandPresenceConfidence options.minTrackingConfidence = minHandTrackingConfidence options.numHands = numHands let gestureRecognizer = try GestureRecognizer(options: options)
Видео
import MediaPipeTasksVision let modelPath = Bundle.main.path(forResource: "gesture_recognizer", ofType: "task") let options = GestureRecognizerOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .video options.minHandDetectionConfidence = minHandDetectionConfidence options.minHandPresenceConfidence = minHandPresenceConfidence options.minTrackingConfidence = minHandTrackingConfidence options.numHands = numHands let gestureRecognizer = try GestureRecognizer(options: options)
Прямая трансляция
import MediaPipeTasksVision // Class that conforms to the `GestureRecognizerLiveStreamDelegate` protocol and // implements the method that the gesture recognizer calls once it finishes // performing recognizing hand gestures in each input frame. class GestureRecognizerResultProcessor: NSObject, GestureRecognizerLiveStreamDelegate { func gestureRecognizer( _ gestureRecognizer: GestureRecognizer, didFinishRecognition result: GestureRecognizerResult?, timestampInMilliseconds: Int, error: Error?) { // Process the gesture recognizer result or errors here. } } let modelPath = Bundle.main.path( forResource: "gesture_recognizer", ofType: "task") let options = GestureRecognizerOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .liveStream options.minHandDetectionConfidence = minHandDetectionConfidence options.minHandPresenceConfidence = minHandPresenceConfidence options.minTrackingConfidence = minHandTrackingConfidence options.numHands = numHands // Assign an object of the class to the `gestureRecognizerLiveStreamDelegate` // property. let processor = GestureRecognizerResultProcessor() options.gestureRecognizerLiveStreamDelegate = processor let gestureRecognizer = try GestureRecognizer(options: options)
Цель-C
Изображение
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"gesture_recognizer" ofType:@"task"]; MPPGestureRecognizerOptions *options = [[MPPGestureRecognizerOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeImage; options.minHandDetectionConfidence = minHandDetectionConfidence options.minHandPresenceConfidence = minHandPresenceConfidence options.minTrackingConfidence = minHandTrackingConfidence options.numHands = numHands MPPGestureRecognizer *gestureRecognizer = [[MPPGestureRecognizer alloc] initWithOptions:options error:nil];
Видео
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"gesture_recognizer" ofType:@"task"]; MPPGestureRecognizerOptions *options = [[MPPGestureRecognizerOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeVideo; options.minHandDetectionConfidence = minHandDetectionConfidence options.minHandPresenceConfidence = minHandPresenceConfidence options.minTrackingConfidence = minHandTrackingConfidence options.numHands = numHands MPPGestureRecognizer *gestureRecognizer = [[MPPGestureRecognizer alloc] initWithOptions:options error:nil];
Прямая трансляция
@import MediaPipeTasksVision; // Class that conforms to the `MPPGestureRecognizerLiveStreamDelegate` protocol // and implements the method that the gesture recognizer calls once it finishes // performing gesture recognition on each input frame. @interface APPGestureRecognizerResultProcessor : NSObject@end @implementation APPGestureRecognizerResultProcessor - (void)gestureRecognizer:(MPPGestureRecognizer *)gestureRecognizer didFinishRecognitionWithResult:(MPPGestureRecognizerResult *)gestureRecognizerResult timestampInMilliseconds:(NSInteger)timestampInMilliseconds error:(NSError *)error { // Process the gesture recognizer result or errors here. } @end NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"gesture_recognizer" ofType:@"task"]; MPPGestureRecognizerOptions *options = [[MPPGestureRecognizerOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeLiveStream; options.minHandDetectionConfidence = minHandDetectionConfidence options.minHandPresenceConfidence = minHandPresenceConfidence options.minTrackingConfidence = minHandTrackingConfidence options.numHands = numHands // Assign an object of the class to the `gestureRecognizerLiveStreamDelegate` // property. APPGestureRecognizerResultProcessor *processor = [APPGestureRecognizerResultProcessor new]; options.gestureRecognizerLiveStreamDelegate = processor; MPPGestureRecognizer *gestureRecognizer = [[MPPGestureRecognizer alloc] initWithOptions:options error:nil];
Варианты конфигурации
Эта задача имеет следующие параметры конфигурации для приложений iOS:
Название опции | Описание | Диапазон значений | Значение по умолчанию | |
---|---|---|---|---|
runningMode | Устанавливает режим выполнения задачи. Есть три режима: ИЗОБРАЖЕНИЕ: Режим для ввода одного изображения. ВИДЕО: Режим декодированных кадров видео. LIVE_STREAM: режим прямой трансляции входных данных, например, с камеры. В этом режиме необходимо вызвать resultListener, чтобы настроить прослушиватель на асинхронное получение результатов. В этом режиме gestureRecognizerLiveStreamDelegate необходимо задать экземпляр класса, реализующего GestureRecognizerLiveStreamDelegate , чтобы получать результаты асинхронного распознавания жестов. | { RunningMode.image, RunningMode.video, RunningMode.liveStream } | RunningMode.image | |
num_hands | Максимальное количество рук может быть обнаружено с помощью GestureRecognizer . | Any integer > 0 | 1 | |
min_hand_detection_confidence | Минимальный показатель достоверности, позволяющий считать обнаружение рук успешным в модели обнаружения ладоней. | 0.0 - 1.0 | 0.5 | |
min_hand_presence_confidence | Минимальный показатель достоверности оценки присутствия руки в модели обнаружения ориентиров рук. В режиме «Видео» и режиме прямой трансляции Распознаватель жестов, если показатель достоверности присутствия руки по модели ориентира руки ниже этого порога, активируется модель обнаружения ладони. В противном случае для определения местоположения руки (рук) для последующего обнаружения ориентиров используется упрощенный алгоритм отслеживания рук. | 0.0 - 1.0 | 0.5 | |
min_tracking_confidence | Минимальный показатель достоверности, позволяющий считать отслеживание рук успешным. Это порог IoU ограничивающей рамки между руками в текущем кадре и последнем кадре. В режиме «Видео» и «Потоковый режим» Распознаватель жестов, если отслеживание не удается, Распознаватель жестов запускает обнаружение рук. В противном случае обнаружение руки пропускается. | 0.0 - 1.0 | 0.5 | |
canned_gestures_classifier_options | Параметры настройки поведения классификатора стандартных жестов. Стандартные жесты: ["None", "Closed_Fist", "Open_Palm", "Pointing_Up", "Thumb_Down", "Thumb_Up", "Victory", "ILoveYou"] |
|
| |
custom_gestures_classifier_options | Параметры настройки поведения классификатора пользовательских жестов. |
|
| |
result_listener | Настраивает прослушиватель результатов на асинхронное получение результатов классификации, когда распознаватель жестов находится в режиме прямого потока. Может использоваться только в том случае, если для режима работы установлено значение LIVE_STREAM | ResultListener | Н/Д | Н/Д |
Если в качестве рабочего режима установлена прямая трансляция, распознавателю жестов требуется дополнительный параметр gestureRecognizerLiveStreamDelegate
, который позволяет распознавателю жестов асинхронно доставлять результаты распознавания жестов. Делегат должен реализовать метод gestureRecognizer(_:didFinishRecognition:timestampInMilliseconds:error:)
, который Распознаватель жестов вызывает после обработки результатов выполнения распознавания жестов в каждом кадре.
Название опции | Описание | Диапазон значений | Значение по умолчанию |
---|---|---|---|
gestureRecognizerLiveStreamDelegate | Позволяет распознавателю жестов асинхронно получать результаты распознавания жестов в режиме прямой трансляции. Класс, экземпляру которого присвоено это свойство, должен реализовать метод gestureRecognizer(_:didFinishRecognition: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
после некоторой обработки с использованием платформы iOSCoreImage
, могут быть отправлены в Распознаватель жестов в режиме работы изображения.Видео: видеокадры можно конвертировать в формат
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 для разработчиков .
Запустить задачу
Чтобы запустить Распознаватель жестов, используйте метод recognize()
специфичный для назначенного режима работы:
- Неподвижное изображение:
recognize(image:)
- Видео:
recognize(videoFrame:timestampInMilliseconds:)
- Прямая трансляция:
recognizeAsync(image:timestampInMilliseconds:)
В следующих примерах кода показаны основные примеры запуска Распознаватель жестов в различных режимах работы:
Быстрый
Изображение
let result = try gestureRecognizer.recognize(image: image)
Видео
let result = try gestureRecognizer.recognize( videoFrame: image, timestampInMilliseconds: timestamp)
Прямая трансляция
try gestureRecognizer.recognizeAsync( image: image, timestampInMilliseconds: timestamp)
Цель-C
Изображение
MPPGestureRecognizerResult *result = [gestureRecognizer recognizeImage:mppImage error:nil];
Видео
MPPGestureRecognizerResult *result = [gestureRecognizer recognizeVideoFrame:image timestampInMilliseconds:timestamp error:nil];
Прямая трансляция
BOOL success = [gestureRecognizer recognizeAsyncImage:image timestampInMilliseconds:timestamp error:nil];
Пример кода позволяет пользователю переключаться между режимами обработки, которые могут не потребоваться для вашего варианта использования.
Обратите внимание на следующее:
При работе в режиме видео или в режиме прямой трансляции вы также должны предоставить метку времени входного кадра задаче Распознавателя жестов.
При работе в режиме изображения или видео задача «Распознаватель жестов» блокирует текущий поток до тех пор, пока не завершит обработку входного изображения или кадра. Чтобы избежать блокировки текущего потока, выполните обработку в фоновом потоке с помощью платформ iOS Dispatch или NSOperation .
При работе в режиме прямой трансляции задача «Распознаватель жестов» возвращается немедленно и не блокирует текущий поток. Он вызывает
gestureRecognizer(_:didFinishRecognition:timestampInMilliseconds:error:)
с результатом распознавания жестов после обработки каждого входного кадра. Распознаватель жестов вызывает этот метод асинхронно в выделенной последовательной очереди отправки. Для отображения результатов в пользовательском интерфейсе отправьте результаты в основную очередь после обработки результатов. Если функцияrecognizeAsync
вызывается, когда задача Распознаватель жестов занята обработкой другого кадра, Распознаватель жестов игнорирует новый входной кадр.
Обработка и отображение результатов
После выполнения вывода задача Распознавателя жестов возвращает GestureRecognizerResult
, который содержит ориентиры рук в координатах изображения, ориентиры рук в мировых координатах, категории рук (левая/правая) и жесты рук обнаруженных рук.
Ниже показан пример выходных данных этой задачи:
Полученный результат GestureRecognizerResult
содержит четыре компонента, каждый из которых представляет собой массив, где каждый элемент содержит обнаруженный результат одной обнаруженной руки.
Рукава
Handedness показывает, являются ли обнаруженные руки левыми или правыми.
Жесты
Распознанные категории жестов обнаруженных рук.
Достопримечательности
Имеется 21 ручной ориентир, каждый из которых состоит из координат
x
,y
иz
. Координатыx
иy
нормализуются на [0,0, 1,0] по ширине и высоте изображения соответственно. Координатаz
представляет глубину ориентира, при этом глубина на запястье является началом координат. Чем меньше значение, тем ближе ориентир к камере. Величинаz
использует примерно тот же масштаб, что иx
.Достопримечательности мира
21 ориентир также представлен в мировых координатах. Каждый ориентир состоит из
x
,y
иz
, представляющих реальные трехмерные координаты в метрах с началом координат в геометрическом центре руки.
GestureRecognizerResult:
Handedness:
Categories #0:
index : 0
score : 0.98396
categoryName : Left
Gestures:
Categories #0:
score : 0.76893
categoryName : Thumb_Up
Landmarks:
Landmark #0:
x : 0.638852
y : 0.671197
z : -3.41E-7
Landmark #1:
x : 0.634599
y : 0.536441
z : -0.06984
... (21 landmarks for a hand)
WorldLandmarks:
Landmark #0:
x : 0.067485
y : 0.031084
z : 0.055223
Landmark #1:
x : 0.063209
y : -0.00382
z : 0.020920
... (21 world landmarks for a hand)
На следующих изображениях показана визуализация результатов задачи: