Задача «Распознаватель жестов MediaPipe» позволяет распознавать жесты рук в реальном времени и предоставляет результаты распознанных жестов рук и ориентиры обнаруженных рук. В этих инструкциях показано, как использовать Распознаватель жестов с приложениями Android. Пример кода, описанный в этой инструкции, доступен на GitHub .
Вы можете увидеть эту задачу в действии, просмотрев веб-демо . Дополнительные сведения о возможностях, моделях и параметрах конфигурации этой задачи см. в разделе Обзор .
Пример кода
Пример кода задач MediaPipe — это простая реализация приложения распознавания жестов для Android. В примере используется камера на физическом устройстве Android для постоянного обнаружения жестов рук, а также могут использоваться изображения и видео из галереи устройства для статического обнаружения жестов.
Вы можете использовать это приложение в качестве отправной точки для своего собственного приложения для Android или обращаться к нему при изменении существующего приложения. Пример кода Распознавателя жестов размещен на 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/android
После создания локальной версии кода примера вы можете импортировать проект в Android Studio и запустить приложение. Инструкции см. в Руководстве по установке для Android .
Ключевые компоненты
Следующие файлы содержат ключевой код для этого примера приложения распознавания жестов рук:
- GestureRecouncerHelper.kt — инициализирует распознаватель жестов и обрабатывает выбор модели и делегата.
- MainActivity.kt — реализует приложение, включая вызов
GestureRecognizerHelper
иGestureRecognizerResultsAdapter
. - GestureRecouncerResultsAdapter.kt — обрабатывает и форматирует результаты.
Настраивать
В этом разделе описаны ключевые шаги по настройке среды разработки и проектов кода специально для использования Распознаватель жестов. Общие сведения о настройке среды разработки для использования задач MediaPipe, включая требования к версии платформы, см. в руководстве по настройке для Android .
Зависимости
Задача Распознавателя жестов использует библиотеку com.google.mediapipe:tasks-vision
. Добавьте эту зависимость в файл build.gradle
вашего приложения Android:
dependencies {
implementation 'com.google.mediapipe:tasks-vision:latest.release'
}
Модель
Для задачи Распознавателя жестов MediaPipe требуется пакет обученной модели, совместимый с этой задачей. Дополнительную информацию о доступных обученных моделях для Распознаватель жестов см. в разделе «Модели » обзора задач.
Выберите и загрузите модель и сохраните ее в каталоге вашего проекта:
<dev-project-root>/src/main/assets
Укажите путь к модели в параметре ModelAssetPath
. В примере кода модель определена в файле GestureRecognizerHelper.kt
:
baseOptionBuilder.setModelAssetPath(MP_RECOGNIZER_TASK)
Создать задачу
Задача Распознавателя жестов MediaPipe использует функцию createFromOptions()
для настройки задачи. Функция createFromOptions()
принимает значения параметров конфигурации. Дополнительные сведения о параметрах конфигурации см. в разделе Параметры конфигурации .
Распознаватель жестов поддерживает три типа входных данных: неподвижные изображения, видеофайлы и прямые видеопотоки. При создании задачи вам необходимо указать режим работы, соответствующий вашему типу входных данных. Выберите вкладку, соответствующую вашему типу входных данных, чтобы узнать, как создать задачу и выполнить вывод.
Изображение
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_RECOGNIZER_TASK) val baseOptions = baseOptionBuilder.build() val optionsBuilder = GestureRecognizer.GestureRecognizerOptions.builder() .setBaseOptions(baseOptions) .setMinHandDetectionConfidence(minHandDetectionConfidence) .setMinTrackingConfidence(minHandTrackingConfidence) .setMinHandPresenceConfidence(minHandPresenceConfidence) .setRunningMode(RunningMode.IMAGE) val options = optionsBuilder.build() gestureRecognizer = GestureRecognizer.createFromOptions(context, options)
Видео
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_RECOGNIZER_TASK) val baseOptions = baseOptionBuilder.build() val optionsBuilder = GestureRecognizer.GestureRecognizerOptions.builder() .setBaseOptions(baseOptions) .setMinHandDetectionConfidence(minHandDetectionConfidence) .setMinTrackingConfidence(minHandTrackingConfidence) .setMinHandPresenceConfidence(minHandPresenceConfidence) .setRunningMode(RunningMode.VIDEO) val options = optionsBuilder.build() gestureRecognizer = GestureRecognizer.createFromOptions(context, options)
Прямая трансляция
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_RECOGNIZER_TASK) val baseOptions = baseOptionBuilder.build() val optionsBuilder = GestureRecognizer.GestureRecognizerOptions.builder() .setBaseOptions(baseOptions) .setMinHandDetectionConfidence(minHandDetectionConfidence) .setMinTrackingConfidence(minHandTrackingConfidence) .setMinHandPresenceConfidence(minHandPresenceConfidence) .setResultListener(this::returnLivestreamResult) .setErrorListener(this::returnLivestreamError) .setRunningMode(RunningMode.LIVE_STREAM) val options = optionsBuilder.build() gestureRecognizer = GestureRecognizer.createFromOptions(context, options)
Реализация примера кода Распознаватель жестов позволяет пользователю переключаться между режимами обработки. Такой подход усложняет код создания задачи и может не подойти для вашего варианта использования. Вы можете увидеть этот код в функции setupGestureRecognizer()
в файле GestureRecognizerHelper.kt
.
Варианты конфигурации
Эта задача имеет следующие параметры конфигурации для приложений Android:
Название опции | Описание | Диапазон значений | Значение по умолчанию | |
---|---|---|---|---|
runningMode | Устанавливает режим выполнения задачи. Есть три режима: ИЗОБРАЖЕНИЕ: Режим для ввода одного изображения. ВИДЕО: Режим декодированных кадров видео. LIVE_STREAM: режим прямой трансляции входных данных, например с камеры. В этом режиме необходимо вызвать resultListener, чтобы настроить прослушиватель на асинхронное получение результатов. | { IMAGE, VIDEO, LIVE_STREAM } | IMAGE | |
numHands | Максимальное количество рук может быть обнаружено с помощью GestureRecognizer . | Any integer > 0 | 1 | |
minHandDetectionConfidence | Минимальный показатель достоверности, позволяющий считать обнаружение рук успешным в модели обнаружения ладоней. | 0.0 - 1.0 | 0.5 | |
minHandPresenceConfidence | Минимальный показатель достоверности оценки присутствия руки в модели обнаружения ориентиров рук. В режиме «Видео» и режиме прямой трансляции Распознаватель жестов, если показатель достоверности присутствия руки по модели ориентира руки ниже этого порога, активируется модель обнаружения ладони. В противном случае для определения местоположения руки (рук) для последующего обнаружения ориентиров используется упрощенный алгоритм отслеживания рук. | 0.0 - 1.0 | 0.5 | |
minTrackingConfidence | Минимальный показатель достоверности, позволяющий считать отслеживание рук успешным. Это порог IoU ограничивающей рамки между руками в текущем кадре и последнем кадре. В режиме «Видео» и «Потоковый режим» Распознаватель жестов, если отслеживание не удается, Распознаватель жестов запускает обнаружение рук. В противном случае обнаружение руки пропускается. | 0.0 - 1.0 | 0.5 | |
cannedGesturesClassifierOptions | Параметры настройки поведения классификатора стандартных жестов. Стандартные жесты: ["None", "Closed_Fist", "Open_Palm", "Pointing_Up", "Thumb_Down", "Thumb_Up", "Victory", "ILoveYou"] |
|
| |
customGesturesClassifierOptions | Параметры настройки поведения классификатора пользовательских жестов. |
|
| |
resultListener | Настраивает прослушиватель результатов на асинхронное получение результатов классификации, когда распознаватель жестов находится в режиме прямого потока. Может использоваться только в том случае, если для режима работы установлено значение LIVE_STREAM | ResultListener | Н/Д | Н/Д |
errorListener | Устанавливает дополнительный прослушиватель ошибок. | ErrorListener | Н/Д | Н/Д |
Подготовьте данные
Распознаватель жестов работает с изображениями, видеофайлами и потоковым видео в реальном времени. Задача выполняет предварительную обработку входных данных, включая изменение размера, поворот и нормализацию значений.
Следующий код демонстрирует, как передать данные для обработки. Эти примеры включают подробную информацию о том, как обрабатывать данные из изображений, видеофайлов и потоков видео в реальном времени.
Изображение
import com.google.mediapipe.framework.image.BitmapImageBuilder import com.google.mediapipe.framework.image.MPImage // Convert the input Bitmap object to an MPImage object to run inference val mpImage = BitmapImageBuilder(image).build()
Видео
import com.google.mediapipe.framework.image.BitmapImageBuilder import com.google.mediapipe.framework.image.MPImage val argb8888Frame = if (frame.config == Bitmap.Config.ARGB_8888) frame else frame.copy(Bitmap.Config.ARGB_8888, false) // Convert the input Bitmap object to an MPImage object to run inference val mpImage = BitmapImageBuilder(argb8888Frame).build()
Прямая трансляция
import com.google.mediapipe.framework.image.BitmapImageBuilder import com.google.mediapipe.framework.image.MPImage // Convert the input Bitmap object to an MPImage object to run inference val mpImage = BitmapImageBuilder(rotatedBitmap).build()
В примере кода Распознавателя жестов подготовка данных выполняется в файле GestureRecognizerHelper.kt
.
Запустить задачу
Распознаватель жестов использует recognize
, recognizeForVideo
и recognizeAsync
для запуска логических выводов. Для распознавания жестов это включает предварительную обработку входных данных, обнаружение рук на изображении, обнаружение ориентиров рук и распознавание жестов рук по ориентирам.
Следующий код демонстрирует, как выполнить обработку с помощью модели задачи. Эти примеры включают подробную информацию о том, как обрабатывать данные из изображений, видеофайлов и потоков видео в реальном времени.
Изображение
val result = gestureRecognizer?.recognize(mpImage)
Видео
val timestampMs = i * inferenceIntervalMs gestureRecognizer?.recognizeForVideo(mpImage, timestampMs) ?.let { recognizerResult -> resultList.add(recognizerResult) }
Прямая трансляция
val mpImage = BitmapImageBuilder(rotatedBitmap).build() val frameTime = SystemClock.uptimeMillis() gestureRecognizer?.recognizeAsync(mpImage, frameTime)
Обратите внимание на следующее:
- При работе в режиме видео или режиме прямой трансляции вы также должны предоставить метку времени входного кадра задаче Распознавателя жестов.
- При работе в режиме изображения или видео задача «Распознаватель жестов» блокирует текущий поток до тех пор, пока он не завершит обработку входного изображения или кадра. Чтобы избежать блокировки пользовательского интерфейса, выполняйте обработку в фоновом потоке.
- При работе в режиме прямой трансляции задача «Распознаватель жестов» не блокирует текущий поток, а немедленно возвращается. Он будет вызывать свой прослушиватель результатов с результатом распознавания каждый раз, когда завершает обработку входного кадра. Если функция распознавания вызывается, когда задача «Распознаватель жестов» занята обработкой другого кадра, задача будет игнорировать новый входной кадр.
В примере кода Распознавателя жестов recognize
, recognizeForVideo
recognizeAsync
в файле GestureRecognizerHelper.kt
.
Обработка и отображение результатов
Распознаватель жестов генерирует объект результата обнаружения жестов для каждого запуска распознавания. Объект результата содержит ориентиры рук в координатах изображения, ориентиры рук в мировых координатах, категории рук (левая/правая) и категории жестов обнаруженных рук.
Ниже показан пример выходных данных этой задачи:
Полученный результат 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)
На следующих изображениях показана визуализация результатов задачи:
В примере кода Распознавателя жестов класс GestureRecognizerResultsAdapter
в файле GestureRecognizerResultsAdapter.kt
обрабатывает результаты.