Skip to main content

Multi-backend parametric body models (SMPL, SMPLX, FLAME, SKEL, ANNY, MHR) for NumPy, PyTorch, and JAX

Project description

body-models

A unified library for parametric human body models.

Provides a ~shared interface across SMPL, SMPL-X, SKEL, FLAME, ANNY, and MHR body models.

Supports:

  • PyTorch, NumPy, and JAX backends
  • forward kinematics disentangled from mesh skinning (forward_skeleton and forward_vertices methods)
  • out-of-the-box lower-resolution mesh forward pass (simplify argument to the constructor)
  • arbitrary number of leading dimensions

Installation

pip install body-models

Or with uv:

uv add body-models

Optional backends

PyTorch and JAX are optional dependencies. Install them for the corresponding backends:

# For PyTorch backend
pip install body-models[torch]

# For JAX backend
pip install body-models[jax]

Note: MHR model requires PyTorch for loading the model file (stored in .pt format).

Model Setup

Auto-download models

ANNY and MHR models are automatically downloaded on first use:

from body_models.anny.torch import ANNY
from body_models.mhr.torch import MHR

model = ANNY()  # Downloads automatically (CC0 license)
model = MHR()   # Downloads automatically (Apache 2.0)

Registration-required models

SMPL, SMPL-X, SKEL, and FLAME require registration. Download from:

For SMPL, convert the pkl file to npz format (the pkl files use chumpy):

convert-smpl-pkl /path/to/model.pkl /path/to/model.npz

Then configure the paths (per gender):

body-models set smpl-neutral /path/to/SMPL_NEUTRAL.npz
body-models set smpl-male /path/to/SMPL_MALE.npz
body-models set smpl-female /path/to/SMPL_FEMALE.npz
body-models set smplx-neutral /path/to/SMPLX_NEUTRAL.npz
body-models set skel /path/to/skel
body-models set flame /path/to/flame

Or pass file paths directly:

from body_models.smpl.torch import SMPL

# Direct file path (no gender needed)
model = SMPL(model_path="/path/to/SMPL_NEUTRAL.npz")

# From config using gender
model = SMPL(gender="neutral")  # Uses smpl-neutral config key

Configuration

View current settings:

$ body-models
Config file: /path/to/config.toml  # Platform-dependent location

Current settings:
  smpl-male: /data/models/smpl/SMPL_MALE.npz
  smpl-female: /data/models/smpl/SMPL_FEMALE.npz
  smpl-neutral: /data/models/smpl/SMPL_NEUTRAL.npz
  smplx-male: (not set)
  smplx-female: (not set)
  smplx-neutral: (not set)
  skel: (not set)
  flame: (not set)
  anny: (not set)
  mhr: (not set)

Manage paths:

body-models set <model> <path>   # Set model path
body-models unset <model>        # Remove from config

Quick Start

# Import from specific backend (torch, numpy, or jax)
from body_models.smplx.torch import SMPLX

# Load model from config
model = SMPLX(gender="neutral")  # Uses smplx-neutral config key

# Or load from direct file path
model = SMPLX(model_path="/path/to/SMPLX_NEUTRAL.npz")

# Get default parameters
params = model.get_rest_pose(batch_size=4)

# Generate mesh vertices
vertices = model.forward_vertices(**params)  # [4, V, 3]

# Get skeleton transforms
skeleton = model.forward_skeleton(**params)  # [4, J, 4, 4]

Available backends:

  • body_models.<model>.torch - PyTorch (differentiable)
  • body_models.<model>.numpy - NumPy
  • body_models.<model>.jax - JAX/Flax (differentiable)

Common Properties

All models inherit from BodyModel and share these properties:

Property Type Description
num_joints int Number of skeleton joints
num_vertices int Number of mesh vertices
faces [F, 3] Mesh face indices
skin_weights [V, J] Skinning weights
rest_vertices [V, 3] Vertices in rest pose

Mesh Simplification

All models support mesh simplification via the simplify constructor argument:

# Reduce face count by half (2x simplification)
model = SMPL(gender="neutral", simplify=2.0)

# Reduce to ~1/4 of original faces
model = SMPLX(gender="neutral", simplify=4.0)

The simplify parameter is a divisor for the face count. A value of 2.0 produces a mesh with half the faces, 4.0 produces quarter, etc. Default is 1.0 (no simplification). Skinning weights and blend shapes are automatically mapped to the simplified mesh.

Common Methods

# Get zero-initialized parameters (model-specific keys)
params = model.get_rest_pose(batch_size=1)

# Compute mesh vertices [B, V, 3] in meters
vertices = model.forward_vertices(**params)

# Compute joint transforms [B, J, 4, 4] in meters
transforms = model.forward_skeleton(**params)

Supported Models

SMPL

The original parametric body model with 6890 vertices and 24 joints.

from body_models.smpl.torch import SMPL  # or .numpy, .jax

model = SMPL(gender="neutral")  # "neutral", "male", or "female"

vertices = model.forward_vertices(
    shape,               # [B, 10] body shape betas
    body_pose,           # [B, 23, 3] axis-angle per joint
    pelvis_rotation,     # [B, 3] root joint rotation (optional)
    global_rotation,     # [B, 3] post-transform rotation (optional)
    global_translation,  # [B, 3] translation (optional)
)

Conversion functions for working with the official smplx library format:

from body_models import smpl

# Convert flat tensors to API format
args = smpl.from_native_args(shape, body_pose, pelvis_rotation, global_translation)
vertices = model.forward_vertices(**args)
transforms = model.forward_skeleton(**args)

# Convert outputs back to native format (removes feet offset, extracts joint positions)
result = smpl.to_native_outputs(vertices, transforms, model._feet_offset)

SMPL-X

Expressive body model with articulated hands and facial expressions.

from body_models.smplx.torch import SMPLX  # or .numpy, .jax

model = SMPLX(
    gender="neutral",     # "neutral", "male", or "female"
    flat_hand_mean=False, # Flat hands as mean pose
)

vertices = model.forward_vertices(
    shape,               # [B, 10] body shape betas
    body_pose,           # [B, 21, 3] axis-angle per body joint
    hand_pose,           # [B, 30, 3] axis-angle (left 15 + right 15)
    head_pose,           # [B, 3, 3] jaw + left eye + right eye
    expression,          # [B, 10] facial expression (optional)
    pelvis_rotation,     # [B, 3] root joint rotation (optional)
    global_rotation,     # [B, 3] post-transform rotation (optional)
    global_translation,  # [B, 3] translation (optional)
)

Conversion functions for working with the official smplx library format:

from body_models import smplx

# Convert flat tensors to API format
args = smplx.from_native_args(shape, expression, body_pose, hand_pose, head_pose,
                              pelvis_rotation, global_translation)
vertices = model.forward_vertices(**args)
transforms = model.forward_skeleton(**args)

# Convert outputs back to native format
result = smplx.to_native_outputs(vertices, transforms, model._feet_offset)

SKEL

Anatomically realistic skeletal articulation based on OpenSim. Only "male" and "female" genders are supported (no "neutral").

from body_models.skel.torch import SKEL  # or .numpy, .jax

model = SKEL(gender="male")  # "male" or "female" (no neutral)

vertices = model.forward_vertices(
    shape,               # [B, 10] body shape betas
    pose,                # [B, 46] anatomically constrained DOFs
    global_rotation,     # [B, 3] axis-angle (optional)
    global_translation,  # [B, 3] (optional)
)

FLAME

FLAME (Faces Learned with an Articulated Model and Expressions) head model.

from body_models.flame.torch import FLAME  # or .numpy, .jax

model = FLAME()  # Uses configured path

vertices = model.forward_vertices(
    shape,               # [B, 300] shape betas (can use fewer)
    expression,          # [B, 100] expression coefficients (optional)
    pose,                # [B, 4, 3] axis-angle for neck, jaw, left_eye, right_eye (optional)
    head_rotation,       # [B, 3] root joint rotation (optional)
    global_rotation,     # [B, 3] post-transform rotation (optional)
    global_translation,  # [B, 3] translation (optional)
)

Conversion functions for working with the official FLAME/smplx library format:

from body_models import flame

# Convert native args to API format
args = flame.from_native_args(shape, expression, pose, head_rotation, global_rotation, global_translation)
vertices = model.forward_vertices(**args)
transforms = model.forward_skeleton(**args)

# Convert outputs back to native format
result = flame.to_native_outputs(vertices, transforms)

ANNY

Phenotype-based body model with intuitive shape parameters.

from body_models.anny.torch import ANNY  # or .numpy, .jax

model = ANNY(
    rig="default",                # "default", "default_no_toes", "cmu_mb", "game_engine", "mixamo"
    topology="default",           # "default" or "makehuman"
    all_phenotypes=False,         # Include race/cupsize/firmness
    extrapolate_phenotypes=False, # Allow values outside [0, 1]
)

vertices = model.forward_vertices(
    gender,              # [B] in [0, 1] (0=male, 1=female)
    age,                 # [B] in [0, 1]
    muscle,              # [B] in [0, 1]
    weight,              # [B] in [0, 1]
    height,              # [B] in [0, 1]
    proportions,         # [B] in [0, 1]
    pose,                # [B, J, 3] axis-angle per joint
    global_rotation,     # [B, 3] axis-angle (optional)
    global_translation,  # [B, 3] (optional)
)

MHR

Meta Human Renderer with neural pose correctives. Requires PyTorch for model loading.

from body_models.mhr.torch import MHR  # or .numpy, .jax (all require torch for loading)

model = MHR(lod=1)  # Level of detail

vertices = model.forward_vertices(
    shape,               # [B, 45] identity blendshapes
    pose,                # [B, 204] pose parameters
    expression,          # [B, 72] facial expression (optional)
    global_rotation,     # [B, 3] axis-angle (optional)
    global_translation,  # [B, 3] (optional)
)

Conversion functions for working with the original MHR format (cm units):

from body_models import mhr

# Convert native args (shape, expression, pose order) to API format
args = mhr.from_native_args(shape, expression, pose)
vertices = model.forward_vertices(**args)
transforms = model.forward_skeleton(**args)

# Convert outputs to native format (cm units, skeleton state [t, q, s])
result = mhr.to_native_outputs(vertices, transforms)

Coordinate System

The unified API returns outputs in:

  • Y-up coordinate system
  • Meters as the unit
  • Feet at floor level (Y=0)

Use the to_native_outputs() conversion functions to get outputs in the original library conventions.

Development

uvx ruff format .   # Format code
uvx ruff check .    # Lint
uvx ty check        # Type check

License

See individual model licenses for usage terms:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

body_models-0.5.0.tar.gz (59.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

body_models-0.5.0-py3-none-any.whl (92.6 kB view details)

Uploaded Python 3

File details

Details for the file body_models-0.5.0.tar.gz.

File metadata

  • Download URL: body_models-0.5.0.tar.gz
  • Upload date:
  • Size: 59.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.5 {"installer":{"name":"uv","version":"0.10.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for body_models-0.5.0.tar.gz
Algorithm Hash digest
SHA256 bb9433dc98e8db820dc925f477c4bff68f5e1783f015d7f28e4aa1990da291e2
MD5 2c1875f99e87ff288b65b340cf33c7f2
BLAKE2b-256 a6f126d22f7c986e932c20b2f0cf2d2a09683429846965d7143a56d0b69b06fa

See more details on using hashes here.

File details

Details for the file body_models-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: body_models-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 92.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.5 {"installer":{"name":"uv","version":"0.10.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for body_models-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ec9aca8eab75ea6bdae05a05d951d4e92cba4cc7388e1f4af31d7381f69593fc
MD5 d8e30f295d3e73658ba14c4537886b96
BLAKE2b-256 d1c7f297eb2172eb0c05c7ae8944560f86fef36485516668d434bd4c784216f5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page