Downloads · 30 days
0
py-feat/emotion_to_mesh
emotion_to_mesh is a machine learning model from py-feat. Use it for the machine learning task on the model card, and read the license before you ship it in a product. It is set up for py-feat. The card lists the license as mit.
Current default: emotiontomeshplsv6.npz (Detectorv2 v2.8 emotion space; py-feat loademotionfacemeshmodel() / plotfacemesh(emotion=...)).
Downloads · 30 days
0
Access
Public
Updated Oct 6, 2026
Repo size
2.2 MB
Likes
0
Public
Click a slice to open those files.
.png2 MB · 93%
From the Hugging Face model README
Current default: emotion_to_mesh_pls_v6.npz (Detectorv2 v2.8 emotion space; py-feat
load_emotion_face_mesh_model() / plot_face_mesh(emotion=...)).
emotion_to_mesh_pls_v5.npzis deprecated — its column labels are permuted. Column j of v5 holds the network's j-th output (Neutral, Happy, Sad, Surprise, Fear, Disgust, Anger) but is labelled inFEAT_EMOTION_COLUMNSorder (anger, disgust, fear, happiness, sadness, surprise, neutral). Indexing v5 by its labels renders the wrong expression (e.g. "anger" renders neutral). The file is retained unchanged for reproducibility only.

| file | features / meshes from | held-out R² | CV | notes |
|---|---|---|---|---|
emotion_to_mesh_pls_v6.npz | Detectorv2 v2.8 | 0.305 ± 0.006 | 5-fold GroupKFold by video | current default, k = 27 |
emotion_to_mesh_pls_v5.npz | Detectorv2 v2.x emotion, MediaPipe mesh | 0.206 ± 0.003 | 3-fold GroupKFold by video | deprecated (permuted labels) |
feature_columns = feat.utils.FEAT_EMOTION_COLUMNS
(anger, disgust, fear, happiness, sadness, surprise, neutral). Detectorv2's Fex
emits Neutral, Happy, Sad, Surprise, Fear, Disgust, Anger; py-feat matches
dict / Series / DataFrame inputs by name and accepts either naming. Raw arrays
must be in feature_columns order.
face_multitask_v28.safetensors,
md5 9e174bb3cd05ce8bed7ac64358a40332). Features and target meshes come from
the same forward pass, so the map is self-consistent with what the detector emits.py-feat/au_to_mesh v6.au_to_mesh v4 frontal mean, the same recipe as au_to_mesh_pls_v6, so AU,
emotion and blendshape renders share one frame.[7 emotion | 3 pose | 21 pose × emotion] = 31 features;
kernel PLS equivalent to PLSRegression(scale=True), k chosen by mean
held-out R² (k = 27; knee at 16).mean_neutral_mesh = prediction at one-hot neutral.Relative to one-hot neutral: happiness raises and widens the lip corners; sadness lowers the corners and raises the brows; surprise raises the brows and opens the jaw; fear widens the eyes; anger lowers the brows and narrows the inner-brow gap. All non-neutral emotions also open the mouth somewhat, reflecting the speech-heavy CelebV-HQ frames on which emotional expressions were observed. R² is modest because a 7-way softmax carries little geometric information; use this model for qualitative visualization.
from feat.plotting import plot_face_mesh, predict_face_mesh_from_features
plot_face_mesh(emotion={"Happy": 1.0}) # Detectorv2 or py-feat names
Or with numpy only:
import numpy as np
m = np.load("emotion_to_mesh_pls_v6.npz")
cols = m["feature_columns"].tolist()
x = np.zeros(len(cols) + 3, dtype=np.float32) # [features | Pitch, Yaw, Roll]
x[cols.index(...)] = ...
flat = x @ m["coef"] + m["intercept"] # (1434,)
mesh = np.stack([flat[:478], flat[478:956], flat[956:]], axis=1) # axis-major [x|y|z]
NPZ: coef (k+3, 1434) f32; intercept (1434,) f32; input_columns;
feature_columns (authoritative order; index by name); feature_name;
pose_columns; mean_aligned_mesh (478, 3); mean_neutral_mesh (478, 3);
reference_anchors (12, 3); anchor_indices (12,); n_components;
model_card; training_metadata (JSON).
MIT for this artifact. The upstream detector that generated its training data carries research-only restrictions.