Задача MediaPipe Pose Landmarker позволяет обнаруживать ориентиры человеческих тел на изображении или видео. Вы можете использовать это задание для определения ключевых положений тела, анализа позы и классификации движений. В этой задаче используются модели машинного обучения (ML), которые работают с отдельными изображениями или видео. Задача выводит ориентиры позы тела в координатах изображения и в трехмерных мировых координатах.
Пример кода, описанный в этой инструкции, доступен на GitHub . Дополнительные сведения о возможностях, моделях и параметрах конфигурации этой задачи см. в разделе Обзор .
Пример кода
Пример кода задач MediaPipe — это простая реализация приложения Pose Landmarker для Android. В примере используется камера на физическом устройстве Android для обнаружения поз в непрерывном видеопотоке. Приложение также может определять позы на изображениях и видео из галереи устройства.
Вы можете использовать это приложение в качестве отправной точки для своего собственного приложения для Android или обращаться к нему при изменении существующего приложения. Пример кода Pose Landmarker размещен на GitHub .
Загрузите код
Следующие инструкции показывают, как создать локальную копию кода примера с помощью инструмента командной строки git .
Чтобы загрузить пример кода:
-  Клонируйте репозиторий git, используя следующую команду: git clone https://github.com/google-ai-edge/mediapipe-samples 
- При желании настройте свой экземпляр git на использование разреженной проверки, чтобы у вас были только файлы для примера приложения Pose Landmarker: cd mediapipe-samples git sparse-checkout init --cone git sparse-checkout set examples/pose_landmarker/android 
После создания локальной версии кода примера вы можете импортировать проект в Android Studio и запустить приложение. Инструкции см. в Руководстве по установке для Android .
Ключевые компоненты
Следующие файлы содержат ключевой код для этого примера приложения для определения ориентиров позы:
- PoseLandmarkerHelper.kt — инициализирует ориентир позы и обрабатывает выбор модели и делегата.
- CameraFragment.kt — управляет камерой устройства и обрабатывает входные данные изображения и видео.
-  GalleryFragment.kt — взаимодействует с OverlayViewдля отображения выходного изображения или видео.
- OverlayView.kt — реализует отображение обнаруженных поз.
Настраивать
В этом разделе описаны ключевые шаги по настройке среды разработки и проектов кода специально для использования Pose Landmarker. Общие сведения о настройке среды разработки для использования задач MediaPipe, включая требования к версии платформы, см. в руководстве по настройке для Android .
Зависимости
 Задача Pose Landmarker использует библиотеку com.google.mediapipe:tasks-vision . Добавьте эту зависимость в файл build.gradle вашего приложения Android:
dependencies {
    implementation 'com.google.mediapipe:tasks-vision:latest.release'
}
Модель
Для задачи MediaPipe Pose Landmarker требуется пакет обученной модели, совместимый с этой задачей. Дополнительную информацию о доступных обученных моделях для Pose Landmarker см. в разделе «Модели» обзора задач.
Выберите и загрузите модель и сохраните ее в каталоге вашего проекта:
<dev-project-root>/src/main/assets
 Укажите путь к модели в параметре ModelAssetPath . В примере кода модель определена в файле PoseLandmarkerHelper.kt :
val modelName = "pose_landmarker_lite.task"
baseOptionsBuilder.setModelAssetPath(modelName)
Создать задачу
 Задача MediaPipe Pose Landmarker использует функцию createFromOptions() для настройки задачи. Функция createFromOptions() принимает значения параметров конфигурации. Дополнительные сведения о параметрах конфигурации см. в разделе Параметры конфигурации .
Pose Landmarker поддерживает следующие типы входных данных: неподвижные изображения, видеофайлы и прямые видеопотоки. При создании задачи вам необходимо указать режим работы, соответствующий вашему типу входных данных. Выберите вкладку для вашего типа входных данных, чтобы узнать, как создать задачу.
Изображение
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName)
val baseOptions = baseOptionBuilder.build()
val optionsBuilder = 
    poseLandmarker.poseLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinPoseDetectionConfidence(minPoseDetectionConfidence)
        .setMinTrackingConfidence(minPoseTrackingConfidence)
        .setMinPosePresenceConfidence(minposePresenceConfidence)
        .setNumPoses(maxNumPoses)
        .setRunningMode(RunningMode.IMAGE)
val options = optionsBuilder.build()
poseLandmarker = poseLandmarker.createFromOptions(context, options)
    Видео
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName)
val baseOptions = baseOptionBuilder.build()
val optionsBuilder = 
    poseLandmarker.poseLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinPoseDetectionConfidence(minPoseDetectionConfidence)
        .setMinTrackingConfidence(minPoseTrackingConfidence)
        .setMinPosePresenceConfidence(minposePresenceConfidence)
        .setNumPoses(maxNumPoses)
        .setRunningMode(RunningMode.VIDEO)
val options = optionsBuilder.build()
poseLandmarker = poseLandmarker.createFromOptions(context, options)
    Прямая трансляция
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName)
val baseOptions = baseOptionBuilder.build()
val optionsBuilder = 
    poseLandmarker.poseLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinPoseDetectionConfidence(minPoseDetectionConfidence)
        .setMinTrackingConfidence(minPoseTrackingConfidence)
        .setMinPosePresenceConfidence(minposePresenceConfidence)
        .setNumPoses(maxNumPoses)
        .setResultListener(this::returnLivestreamResult)
        .setErrorListener(this::returnLivestreamError)
        .setRunningMode(RunningMode.LIVE_STREAM)
val options = optionsBuilder.build()
poseLandmarker = poseLandmarker.createFromOptions(context, options)
     Реализация примера кода Pose Landmarker позволяет пользователю переключаться между режимами обработки. Такой подход усложняет код создания задачи и может не подойти для вашего варианта использования. Вы можете увидеть этот код в функции setupPoseLandmarker() в файле PoseLandmarkerHelper.kt .
Варианты конфигурации
Эта задача имеет следующие параметры конфигурации для приложений Android:
| Название опции | Описание | Диапазон значений | Значение по умолчанию | 
|---|---|---|---|
| runningMode | Устанавливает режим выполнения задачи. Есть три режима: ИЗОБРАЖЕНИЕ: Режим для ввода одного изображения. ВИДЕО: Режим декодированных кадров видео. LIVE_STREAM: режим прямой трансляции входных данных, например с камеры. В этом режиме необходимо вызвать resultListener, чтобы настроить прослушиватель на асинхронное получение результатов. | { IMAGE, VIDEO, LIVE_STREAM} | IMAGE | 
| numposes | Максимальное количество поз, которые может обнаружить ориентир позы. | Integer > 0 | 1 | 
| minPoseDetectionConfidence | Минимальный показатель достоверности, позволяющий считать обнаружение позы успешным. | Float [0.0,1.0] | 0.5 | 
| minPosePresenceConfidence | Минимальный показатель достоверности оценки присутствия позы при обнаружении ориентира позы. | Float [0.0,1.0] | 0.5 | 
| minTrackingConfidence | Минимальный показатель достоверности, позволяющий отслеживанию позы считаться успешным. | Float [0.0,1.0] | 0.5 | 
| outputSegmentationMasks | Выводит ли Pose Landmarker маску сегментации для обнаруженной позы. | Boolean | False | 
| resultListener | Настраивает прослушиватель результатов на асинхронное получение результатов ориентира, когда Pose Landmarker находится в режиме прямой трансляции. Может использоваться только в том случае, если для режима работы установлено значение LIVE_STREAM | ResultListener | N/A | 
| errorListener | Устанавливает дополнительный прослушиватель ошибок. | ErrorListener | N/A | 
Подготовьте данные
Pose Landmarker работает с изображениями, видеофайлами и прямыми видеопотоками. Задача выполняет предварительную обработку входных данных, включая изменение размера, поворот и нормализацию значений.
Следующий код демонстрирует, как передать данные для обработки. Эти примеры включают подробную информацию о том, как обрабатывать данные из изображений, видеофайлов и потоков видео в реальном времени.
Изображение
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()
 В примере кода Pose Landmarker подготовка данных выполняется в файле PoseLandmarkerHelper.kt .
Запустить задачу
 В зависимости от типа данных, с которыми вы работаете, используйте poseLandmarker.detect...() специфичный для этого типа данных. Используйте detect() для отдельных изображений, detectForVideo() для кадров в видеофайлах и detectAsync() для видеопотоков. Когда вы выполняете обнаружения в видеопотоке, убедитесь, что вы запускаете обнаружения в отдельном потоке, чтобы избежать блокировки потока ввода пользователя.
В следующих примерах кода показаны простые примеры запуска Pose Landmarker в этих различных режимах данных:
Изображение
val result = poseLandmarker.detect(mpImage)
    Видео
val timestampMs = i * inferenceIntervalMs poseLandmarker.detectForVideo(mpImage, timestampMs) .let { detectionResult -> resultList.add(detectionResult) }
Прямая трансляция
val mpImage = BitmapImageBuilder(rotatedBitmap).build()
val frameTime = SystemClock.uptimeMillis()
poseLandmarker.detectAsync(mpImage, frameTime)
    Обратите внимание на следующее:
- При работе в режиме видео или режиме прямой трансляции вы должны предоставить метку времени входного кадра задаче Pose Landmarker.
- При работе в режиме изображения или видео задача Pose Landmarker блокирует текущий поток до тех пор, пока не завершится обработка входного изображения или кадра. Чтобы избежать блокировки пользовательского вмешательства, выполняйте обработку в фоновом потоке.
- При работе в режиме прямой трансляции задача Pose Landmarker немедленно возвращается и не блокирует текущий поток. Он будет вызывать прослушиватель результатов с результатом обнаружения каждый раз, когда завершает обработку входного кадра.
 В примере кода Pose Landmarker функции detect , detectForVideo и detectAsync определены в файле PoseLandmarkerHelper.kt .
Обработка и отображение результатов
 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 демонстрирует, как отображать результаты, возвращаемые задачей. Дополнительные сведения см. в классе OverlayView .