Pose Landmarker

The MediaPipe Pose Landmarker task lets you detect landmarks of human bodies in an image or video. You can use this task to identify key body locations, analyze posture, and categorize movements. This task uses machine learning (ML) models that work with single images or video. The task outputs body pose landmarks in image coordinates and in 3-dimensional world coordinates.

Quickstart

Install the SDK for your platform, prepare input data, choose a running mode, and run inference.

Web

npmnpm install @mediapipe/tasks-visionWeb demo·Edit in StackBlitz·Setup guide

Image

IMAGEStateless · single frameSynchronous call on independent still images. Resets temporal tracking state on every call.
import { FilesetResolver, PoseLandmarker } from "@mediapipe/tasks-vision";

const vision = await FilesetResolver.forVisionTasks(
  "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm"
);
const poseLandmarker = await PoseLandmarker.createFromOptions(vision, {
  baseOptions: { modelAssetPath: "pose_landmarker_lite.task", delegate: "GPU" },
  runningMode: "IMAGE",
  numPoses: 1,
});

// Synchronous single-frame call (stateless across images)
const image = document.getElementById("image") as HTMLImageElement;
const result = poseLandmarker.detect(image);

Video

VIDEOEvery frame · no dropsSynchronous tracking across decoded video frames with monotonic timestamps. Processes every frame in order and never drops frames.
import { FilesetResolver, PoseLandmarker } from "@mediapipe/tasks-vision";

const vision = await FilesetResolver.forVisionTasks(
  "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm"
);
const poseLandmarker = await PoseLandmarker.createFromOptions(vision, {
  baseOptions: { modelAssetPath: "pose_landmarker_lite.task", delegate: "GPU" },
  runningMode: "VIDEO",
  numPoses: 1,
});

// Synchronous across decoded frames with monotonic timestamps (never drops frames)
for (const { frame, timestampMs } of decodedVideoFrames) {
  const result = poseLandmarker.detectForVideo(frame, timestampMs);
}

Livestream

VIDEO + rAFLive camera · latest frameWeb tasks run synchronously—pair runningMode: "VIDEO" with requestAnimationFrame so each paint inspects only the latest camera frame (skipping intermediate frames when busy).
import { FilesetResolver, PoseLandmarker } from "@mediapipe/tasks-vision";

const vision = await FilesetResolver.forVisionTasks(
  "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm"
);
// On Web, live camera loops pair runningMode: "VIDEO" with requestAnimationFrame
const poseLandmarker = await PoseLandmarker.createFromOptions(vision, {
  baseOptions: { modelAssetPath: "pose_landmarker_lite.task", delegate: "GPU" },
  runningMode: "VIDEO",
  numPoses: 1,
});

const video = document.getElementById("webcam") as HTMLVideoElement;
video.srcObject = await navigator.mediaDevices.getUserMedia({ video: true });
await video.play();
let lastVideoTime = -1;

function renderLoop() {
  if (video.readyState >= 2 && video.currentTime !== lastVideoTime) {
    lastVideoTime = video.currentTime;
    const result = poseLandmarker.detectForVideo(video, performance.now());
    console.log(result.landmarks, result.worldLandmarks);
  }
  requestAnimationFrame(renderLoop);
}
renderLoop();

Android (Kotlin)

Gradleimplementation("com.google.mediapipe:tasks-vision:latest.release")Sample code·Setup guide

Image

IMAGEStateless · single frameSynchronous call on independent still images. Resets temporal tracking state on every call.
import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage
import com.google.mediapipe.tasks.core.BaseOptions
import com.google.mediapipe.tasks.vision.core.RunningMode
import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarker

val baseOptions = BaseOptions.builder()
    .setModelAssetPath("pose_landmarker_lite.task")
    .build()
val options = PoseLandmarker.PoseLandmarkerOptions.builder()
    .setBaseOptions(baseOptions)
    .setRunningMode(RunningMode.IMAGE)
    .setNumPoses(1)
    .build()

val poseLandmarker = PoseLandmarker.createFromOptions(context, options)

// Synchronous single-image call (no temporal tracking across calls)
val mpImage = BitmapImageBuilder(bitmap).build()
val result = poseLandmarker.detect(mpImage)

Video

VIDEOEvery frame · no dropsSynchronous tracking across decoded video frames with monotonic timestamps. Processes every frame in order and never drops frames.
import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage
import com.google.mediapipe.tasks.core.BaseOptions
import com.google.mediapipe.tasks.vision.core.RunningMode
import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarker

val baseOptions = BaseOptions.builder()
    .setModelAssetPath("pose_landmarker_lite.task")
    .build()
val options = PoseLandmarker.PoseLandmarkerOptions.builder()
    .setBaseOptions(baseOptions)
    .setRunningMode(RunningMode.VIDEO)
    .setNumPoses(1)
    .build()

val poseLandmarker = PoseLandmarker.createFromOptions(context, options)

// Synchronous: processes every frame in order with monotonic timestamps (no frame drops)
val mpImage = BitmapImageBuilder(frameBitmap).build()
val result = poseLandmarker.detectForVideo(mpImage, frameTimestampMs)

Livestream

LIVE_STREAMAsync · drops frames when busyAsynchronous camera pipeline with a result callback. Automatically drops incoming frames when busy so results stay current with low latency.
import android.os.SystemClock
import android.util.Log
import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage
import com.google.mediapipe.tasks.core.BaseOptions
import com.google.mediapipe.tasks.vision.core.RunningMode
import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarker

val baseOptions = BaseOptions.builder()
    .setModelAssetPath("pose_landmarker_lite.task")
    .build()
val options = PoseLandmarker.PoseLandmarkerOptions.builder()
    .setBaseOptions(baseOptions)
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setNumPoses(1)
    .setResultListener { result, _ -> val poses = result.landmarks() }
    .setErrorListener { error -> Log.e("MediaPipe", error.message.orEmpty()) }
    .build()

val poseLandmarker = PoseLandmarker.createFromOptions(context, options)

// Async: automatically drops incoming camera frames when busy so results stay current
poseLandmarker.detectAsync(mpImage, SystemClock.uptimeMillis())

Android (Java)

Gradleimplementation 'com.google.mediapipe:tasks-vision:latest.release'Sample code·Setup guide

Image

IMAGEStateless · single frameSynchronous call on independent still images. Resets temporal tracking state on every call.
import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;
import com.google.mediapipe.tasks.core.BaseOptions;
import com.google.mediapipe.tasks.vision.core.RunningMode;
import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarker;
import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarkerResult;

BaseOptions baseOptions = BaseOptions.builder()
    .setModelAssetPath("pose_landmarker_lite.task")
    .build();
PoseLandmarker.PoseLandmarkerOptions options = PoseLandmarker.PoseLandmarkerOptions.builder()
    .setBaseOptions(baseOptions)
    .setRunningMode(RunningMode.IMAGE)
    .setNumPoses(1)
    .build();

PoseLandmarker poseLandmarker = PoseLandmarker.createFromOptions(context, options);

// Synchronous single-image call (no temporal tracking across calls)
MPImage mpImage = new BitmapImageBuilder(bitmap).build();
PoseLandmarkerResult result = poseLandmarker.detect(mpImage);

Video

VIDEOEvery frame · no dropsSynchronous tracking across decoded video frames with monotonic timestamps. Processes every frame in order and never drops frames.
import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;
import com.google.mediapipe.tasks.core.BaseOptions;
import com.google.mediapipe.tasks.vision.core.RunningMode;
import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarker;
import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarkerResult;

BaseOptions baseOptions = BaseOptions.builder()
    .setModelAssetPath("pose_landmarker_lite.task")
    .build();
PoseLandmarker.PoseLandmarkerOptions options = PoseLandmarker.PoseLandmarkerOptions.builder()
    .setBaseOptions(baseOptions)
    .setRunningMode(RunningMode.VIDEO)
    .setNumPoses(1)
    .build();

PoseLandmarker poseLandmarker = PoseLandmarker.createFromOptions(context, options);

// Synchronous: processes every frame in order with monotonic timestamps (no frame drops)
MPImage mpImage = new BitmapImageBuilder(frameBitmap).build();
PoseLandmarkerResult result = poseLandmarker.detectForVideo(mpImage, frameTimestampMs);

Livestream

LIVE_STREAMAsync · drops frames when busyAsynchronous camera pipeline with a result callback. Automatically drops incoming frames when busy so results stay current with low latency.
import android.os.SystemClock;
import android.util.Log;
import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;
import com.google.mediapipe.tasks.core.BaseOptions;
import com.google.mediapipe.tasks.vision.core.RunningMode;
import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarker;

BaseOptions baseOptions = BaseOptions.builder()
    .setModelAssetPath("pose_landmarker_lite.task")
    .build();
PoseLandmarker.PoseLandmarkerOptions options = PoseLandmarker.PoseLandmarkerOptions.builder()
    .setBaseOptions(baseOptions)
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setNumPoses(1)
    .setResultListener((result, inputImage) -> { var poses = result.landmarks(); })
    .setErrorListener(error -> Log.e("MediaPipe", String.valueOf(error.getMessage())))
    .build();

PoseLandmarker poseLandmarker = PoseLandmarker.createFromOptions(context, options);

// Async: automatically drops incoming camera frames when busy so results stay current
poseLandmarker.detectAsync(mpImage, SystemClock.uptimeMillis());

iOS

SwiftPMhttps://github.com/google-ai-edge/mediapipe → MediaPipeTasksVisionPackage.swift·Sample code·Setup guide

Image

IMAGEStateless · single frameSynchronous call on independent still images. Resets temporal tracking state on every call.
import Foundation
import MediaPipeTasksVision

guard let modelPath = Bundle.main.path(forResource: "pose_landmarker_lite", ofType: "task") else { return }

let options = PoseLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.numPoses = 1

let poseLandmarker = try PoseLandmarker(options: options)

// Synchronous single-image call (stateless across images)
let mpImage = try MPImage(uiImage: image)
let result = try poseLandmarker.detect(image: mpImage)

Video

VIDEOEvery frame · no dropsSynchronous tracking across decoded video frames with monotonic timestamps. Processes every frame in order and never drops frames.
import Foundation
import MediaPipeTasksVision

guard let modelPath = Bundle.main.path(forResource: "pose_landmarker_lite", ofType: "task") else { return }

let options = PoseLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.numPoses = 1

let poseLandmarker = try PoseLandmarker(options: options)

// Synchronous: processes every frame in order with monotonic timestamps (no frame drops)
let mpImage = try MPImage(pixelBuffer: pixelBuffer)
let result = try poseLandmarker.detect(videoFrame: mpImage, timestampInMilliseconds: timestampMs)

Livestream

LIVE_STREAMAsync · drops frames when busyAsynchronous camera pipeline with a result callback. Automatically drops incoming frames when busy so results stay current with low latency.
import Foundation
import MediaPipeTasksVision

final class PoseLandmarkerStreamService: NSObject {
    private var poseLandmarker: PoseLandmarker?

    func setUp() throws {
        guard let modelPath = Bundle.main.path(
            forResource: "pose_landmarker_lite",
            ofType: "task"
        ) else { return }

        let options = PoseLandmarkerOptions()
        options.baseOptions.modelAssetPath = modelPath
        options.runningMode = .liveStream
        options.numPoses = 1
        options.poseLandmarkerLiveStreamDelegate = self

        poseLandmarker = try PoseLandmarker(options: options)
    }

    func detectAsync(mpImage: MPImage, timestampMs: Int) throws {
        // Async: automatically drops incoming camera frames when busy so results stay current
        try poseLandmarker?.detectAsync(image: mpImage, timestampInMilliseconds: timestampMs)
    }
}

extension PoseLandmarkerStreamService: PoseLandmarkerLiveStreamDelegate {
    func poseLandmarker(
        _ poseLandmarker: PoseLandmarker,
        didFinishDetection result: PoseLandmarkerResult?,
        timestampInMilliseconds: Int,
        error: (any Error)?
    ) {
        guard let result else { return }
        DispatchQueue.main.async {
            let poses = result.landmarks
        }
    }
}

Python

pippip install mediapipeSample code·Setup guide

Image

IMAGEStateless · single frameSynchronous call on independent still images. Resets temporal tracking state on every call.
import mediapipe as mp

BaseOptions = mp.tasks.BaseOptions
PoseLandmarker = mp.tasks.vision.PoseLandmarker
PoseLandmarkerOptions = mp.tasks.vision.PoseLandmarkerOptions
VisionRunningMode = mp.tasks.vision.RunningMode

options = PoseLandmarkerOptions(
    base_options=BaseOptions(model_asset_path="pose_landmarker_lite.task"),
    running_mode=VisionRunningMode.IMAGE,
    num_poses=1,
)

with PoseLandmarker.create_from_options(options) as landmarker:
    # Synchronous single-image call (stateless across images)
    mp_image = mp.Image.create_from_file("input.jpg")
    result = landmarker.detect(mp_image)

Video

VIDEOEvery frame · no dropsSynchronous tracking across decoded video frames with monotonic timestamps. Processes every frame in order and never drops frames.
import mediapipe as mp

BaseOptions = mp.tasks.BaseOptions
PoseLandmarker = mp.tasks.vision.PoseLandmarker
PoseLandmarkerOptions = mp.tasks.vision.PoseLandmarkerOptions
VisionRunningMode = mp.tasks.vision.RunningMode

options = PoseLandmarkerOptions(
    base_options=BaseOptions(model_asset_path="pose_landmarker_lite.task"),
    running_mode=VisionRunningMode.VIDEO,
    num_poses=1,
)

with PoseLandmarker.create_from_options(options) as landmarker:
    # Synchronous: processes every frame in order with monotonic timestamps (no frame drops)
    for mp_image, timestamp_ms in decoded_video_frames:
        result = landmarker.detect_for_video(mp_image, timestamp_ms)

Livestream

LIVE_STREAMAsync · drops frames when busyAsynchronous camera pipeline with a result callback. Automatically drops incoming frames when busy so results stay current with low latency.
import mediapipe as mp

BaseOptions = mp.tasks.BaseOptions
PoseLandmarker = mp.tasks.vision.PoseLandmarker
PoseLandmarkerOptions = mp.tasks.vision.PoseLandmarkerOptions
VisionRunningMode = mp.tasks.vision.RunningMode

def on_result(result, output_image: mp.Image, timestamp_ms: int):
    print(f"Detected {len(result.pose_landmarks)} pose(s) at {timestamp_ms} ms")

options = PoseLandmarkerOptions(
    base_options=BaseOptions(model_asset_path="pose_landmarker_lite.task"),
    running_mode=VisionRunningMode.LIVE_STREAM,
    num_poses=1,
    result_callback=on_result,
)

with PoseLandmarker.create_from_options(options) as landmarker:
    # Async: automatically drops incoming camera frames when busy so results stay current
    mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=rgb_frame)
    landmarker.detect_async(mp_image, timestamp_ms)

On Web, you can use DrawingUtils(ctx).drawConnectors(landmarks, PoseLandmarker.POSE_CONNECTIONS) and drawLandmarks(landmarks) from @mediapipe/tasks-vision to render pose skeletons on an HTML <canvas>.

Task details

This section describes the capabilities, inputs, outputs, and configuration options of this task.

Features

  • Input image processing - Processing includes image rotation, resizing, normalization, and color space conversion.
  • Score threshold - Filter results based on prediction scores.
Inputs
The Pose Landmarker accepts an input of one of the following data types:
  • Still images
  • Decoded video frames
  • Live video feed

See Prepare vision input data for MPImage, mp.Image, and browser media examples.

Outputs
The Pose Landmarker outputs the following results:
  • Pose landmarks in normalized image coordinates
  • Pose landmarks in world coordinates
  • Optional: a segmentation mask for the pose.

Configuration options

This task has the following configuration options:

Web

Option Name Description Value Range Default Value
runningMode Sets the running mode for the task:

IMAGE: Single image inputs.
VIDEO: Decoded video frames and live camera streams.
{IMAGE, VIDEO} IMAGE
numPoses The maximum number of poses detected by the Pose Landmarker. Integer > 0 1
minPoseDetectionConfidence The minimum confidence score for pose detection to be considered successful. Float [0.0, 1.0] 0.5
minPosePresenceConfidence The minimum confidence score for pose presence in pose landmark detection. Float [0.0, 1.0] 0.5
minTrackingConfidence The minimum confidence score for pose tracking to be considered successful. Float [0.0, 1.0] 0.5
outputSegmentationMasks Whether Pose Landmarker outputs a foreground segmentation mask for each detected pose (shouldOutputSegmentationMasks on iOS). Boolean false

Android

Option Name Description Value Range Default Value
runningMode Sets the running mode for the task:

IMAGE: Single image inputs.
VIDEO: Decoded frames of a video.
LIVE_STREAM: Livestream of camera input data (requires asynchronous listener/delegate).
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
numPoses The maximum number of poses detected by the Pose Landmarker. Integer > 0 1
minPoseDetectionConfidence The minimum confidence score for pose detection to be considered successful. Float [0.0, 1.0] 0.5
minPosePresenceConfidence The minimum confidence score for pose presence in pose landmark detection. Float [0.0, 1.0] 0.5
minTrackingConfidence The minimum confidence score for pose tracking to be considered successful. Float [0.0, 1.0] 0.5
outputSegmentationMasks Whether Pose Landmarker outputs a foreground segmentation mask for each detected pose (shouldOutputSegmentationMasks on iOS). Boolean false
resultListener Asynchronous callback for LIVE_STREAM mode results. OutputHandler.ResultListener<PoseLandmarkerResult, MPImage> Not set
errorListener Optional error listener for LIVE_STREAM mode. ErrorListener Not set

iOS

Option Name Description Value Range Default Value
runningMode Sets the running mode for the task:

IMAGE: Single image inputs.
VIDEO: Decoded frames of a video.
LIVE_STREAM: Livestream of camera input data (requires asynchronous listener/delegate).
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
numPoses The maximum number of poses detected by the Pose Landmarker. Integer > 0 1
minPoseDetectionConfidence The minimum confidence score for pose detection to be considered successful. Float [0.0, 1.0] 0.5
minPosePresenceConfidence The minimum confidence score for pose presence in pose landmark detection. Float [0.0, 1.0] 0.5
minTrackingConfidence The minimum confidence score for pose tracking to be considered successful. Float [0.0, 1.0] 0.5
shouldOutputSegmentationMasks Whether Pose Landmarker outputs a foreground segmentation mask for each detected pose (shouldOutputSegmentationMasks on iOS). Boolean false
poseLandmarkerLiveStreamDelegate Asynchronous delegate for LIVE_STREAM mode results (invoked on a serial background queue). PoseLandmarkerLiveStreamDelegate Not set

Python

Option Name Description Value Range Default Value
running_mode Sets the running mode for the task:

IMAGE: Single image inputs.
VIDEO: Decoded frames of a video.
LIVE_STREAM: Livestream of camera input data (requires result_callback).
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
num_poses The maximum number of poses detected by the Pose Landmarker. Integer > 0 1
min_pose_detection_confidence The minimum confidence score for pose detection to be considered successful. Float [0.0, 1.0] 0.5
min_pose_presence_confidence The minimum confidence score for pose presence in pose landmark detection. Float [0.0, 1.0] 0.5
min_tracking_confidence The minimum confidence score for pose tracking to be considered successful. Float [0.0, 1.0] 0.5
output_segmentation_masks Whether Pose Landmarker outputs a foreground segmentation mask for each detected pose (shouldOutputSegmentationMasks on iOS). Boolean False
result_callback Asynchronous callback function for LIVE_STREAM mode results. Callable Not set

Task output

Each PoseLandmarkerResult returns normalized image landmarks, 3D world landmarks, and optional segmentation masks for each detected person:

Field Type / Coordinate Space Description
landmarks NormalizedLandmark[][] (x, y in [0.0, 1.0]) 33 3D keypoints per pose (pose_landmarks in Python). x and y are normalized by image width and height; z is depth relative to the midpoint of the hips. Includes visibility and presence probabilities in [0.0, 1.0].
worldLandmarks Landmark[][] (meters) 33 3D keypoints per pose in real-world meters with the midpoint of the hips as the origin (pose_world_landmarks in Python), plus visibility and presence in [0.0, 1.0].
segmentationMasks MPMask[] (Float32 in [0.0, 1.0]) Optional per-pixel person confidence mask when outputSegmentationMasks is enabled (segmentation_masks in Python).

The following example shows the output for a single detected person (pose[0]):

{
  landmarks: [
    [
      { x: 0.6389, y: 0.6712, z: 0.1300, visibility: 0.9999, presence: 0.9999 },  // #0 nose (normalized [0.0, 1.0])
      { x: 0.6346, y: 0.5364, z: -0.0698, visibility: 0.9999, presence: 0.9999 }, // #1 left_eye_inner
      // ... 33 normalized landmarks per detected pose (#0..#32)
    ]
  ],
  worldLandmarks: [
    [
      { x: 0.0675, y: 0.0311, z: 0.0552, visibility: 0.9999, presence: 0.9999 },  // #0 nose (3D meters from hip center)
      { x: 0.0632, y: -0.0038, z: 0.0209, visibility: 0.9999, presence: 0.9999 }, // #1 left_eye_inner
      // ... 33 world landmarks per detected pose (#0..#32)
    ]
  ]
}

Models

Pose Landmarker pipeline overview

The Pose Landmarker uses a series of models to predict pose landmarks. The first model detects the presence of human bodies within an image frame, and the second model locates landmarks on the bodies.

The following models are packaged together into a downloadable model bundle:

  • Pose detection model: detects the presence of bodies with a few key pose landmarks.
  • Pose landmarker model: adds a complete mapping of the pose. The model outputs an estimate of 33 3-dimensional pose landmarks.

This bundle uses a convolutional neural network similar to MobileNetV2 and is optimized for on-device, real-time fitness applications. This variant of the BlazePose model uses GHUM, a 3D human shape modeling pipeline, to estimate the full 3D body pose of an individual in images or videos.

Model bundle Input shape Data type Model Cards Versions
Pose Landmarker (lite) Pose detector: 224 x 224 x 3
Pose landmarker: 256 x 256 x 3
float 16 info Latest
Pose Landmarker (full) Pose detector: 224 x 224 x 3
Pose landmarker: 256 x 256 x 3
float 16 info Latest
Pose Landmarker (heavy) Pose detector: 224 x 224 x 3
Pose landmarker: 256 x 256 x 3
float 16 info Latest

Pose landmarker model

The pose landmarker model tracks 33 body landmark locations, representing the approximate location of the following body parts:

33 3D pose landmarks diagram
ID Landmark ID Landmark
0nose17left_pinky
1left_eye_inner18right_pinky
2left_eye19left_index
3left_eye_outer20right_index
4right_eye_inner21left_thumb
5right_eye22right_thumb
6right_eye_outer23left_hip
7left_ear24right_hip
8right_ear25left_knee
9mouth_left26right_knee
10mouth_right27left_ankle
11left_shoulder28right_ankle
12right_shoulder29left_heel
13left_elbow30right_heel
14right_elbow31left_foot_index
15left_wrist32right_foot_index
16right_wrist

The model output contains both normalized coordinates (Landmarks) and world coordinates (WorldLandmarks) for each landmark.