region_maps¶
feat.utils.region_maps
¶
Facial AU / ARKit-blendshape region overlays on the MediaPipe-478 mesh.
This is the dense-mesh, non-overlapping successor to the dlib-68 muscle
polygons in feat.plotting.draw_muscles and the overlapping muscle map in
feat.utils.muscle_to_landmark. It ships two maps:
au_region_map.json— the 20 FACS AUs, left+right merged per AU.blendshape_region_map.json— the spatially-distinct ARKit blendshapes, Left/Right kept independent (ARKit pre-splits...Left/...Right).
Both are built by a winner-take-all geodesic-Voronoi partition of the mesh:
each vertex is assigned to the single nearest region seed by walking the mesh
surface (Dijkstra over the triangle-edge graph, capped at TIGHTNESS of the
face span), with the eye/mouth aperture rings walling growth off. The partition
is non-overlapping by construction.
The per-vertex partition is then resolved to a per-triangle assignment and cleaned so the region silhouettes are whole rather than ragged, while staying strictly on the 478-mesh triangle edges (no subdivision, no curve fitting — the boundaries never become smoother than the mesh itself):
- each triangle takes the region of its majority vertex (the eye/mouth aperture triangles are permanent holes);
- boundary-length (perimeter) descent flips boundary triangles to shorten
the zigzag region↔region edges, bounded so no region's area drifts past
CAPand tiny regions (<=SMALL_REGIONtriangles) are frozen; - the partition is L/R symmetrized with a geometric (triangle-centroid) mirror map;
- small disconnected specks are removed symmetrically (each speck and its mirror reassigned together), killing stray "flipped" triangles.
The per-triangle assignment is fixed in index space (triangle indices into the
bundled canonical tessellation), so the same map overlays a live detected
478-mesh — only the vertex positions change per frame. See
feat.plotting.plot_face_regions.
The AU <-> muscle <-> blendshape correspondence is grounded in: * FACS (Ekman & Friesen) — AU -> muscle. * Melinda Ozel's ARKit-to-FACS cheat sheet (melindaozel.com/arkit-to-facs-cheat-sheet). * pooyadeperson's "Ultimate Guide to ARKit's 52 Facial Blendshapes" (anatomy refs).
aperture_triangles(tris, aperture)
¶
Triangles wholly inside an eye/mouth aperture (all 3 verts on a ring) — the OPENINGS. They stay permanent holes (never gap-filled or relabeled).
Source code in feat/utils/region_maps.py
build_adjacency(tris, n)
¶
Vertex adjacency over the triangle-edge graph.
Source code in feat/utils/region_maps.py
build_au_region_map()
¶
{AU: {muscles, triangles, mp478_vertices, n_triangles, n_vertices}} —
muscle partition merged to AU (left+right share an AU).
Source code in feat/utils/region_maps.py
build_blendshape_region_map()
¶
{blendshape: {au, muscle, side, triangles, mp478_vertices,
n_triangles, n_vertices}}.
L/R pairs share one symmetric mesh FEATURE (their seeds merged) grown by the geodesic-Voronoi partition; the per-triangle cleanup divides each sided pair cleanly down the midline and forces exact L/R symmetry. Center shapes keep the whole bilateral feature. Non-overlapping by construction.
Source code in feat/utils/region_maps.py
geodesic_voronoi(seeds_by_region, adj, xy, aperture, max_geo)
¶
Winner-take-all surface partition: assign each vertex to the nearest
seed's region by Dijkstra over the edge graph (euclidean edge weights on
xy), capped at max_geo, never crossing aperture verts.
Returns {vertex_index: region_name}. Non-overlapping by construction —
a vertex is claimed once, by whichever region reaches it first/closest.
Source code in feat/utils/region_maps.py
load_au_region_map()
¶
Bundled non-overlapping AU region map (20 AUs, L+R merged). Each value:
{"muscles", "triangles", "mp478_vertices", "n_triangles", "n_vertices"}.
load_blendshape_region_map()
¶
Bundled non-overlapping blendshape region map (L/R independent). Each
value: {"au", "muscle", "side", "triangles", "mp478_vertices",
"n_triangles", "n_vertices"}.
Source code in feat/utils/region_maps.py
project_xy(V)
¶
Frontal x/y projection, flipped so the forehead (v10) is above the chin
(v152). V may be the canonical mesh or a detected mesh (N>=153, x/y in
cols 0/1). Used both for geodesic distances and for plotting.
Source code in feat/utils/region_maps.py
render_assets(kind='au')
¶
Cached rendering assets for kind in {"au", "blendshape"}:
{"tris": int[M,3], "region_tris": {region: [triangle indices]},
"n_base": 468}
tris is the bundled canonical tessellation; region_tris maps each
final region name (an AU, or a sided/center blendshape) to the triangle
indices it owns after the cleanup pipeline. Fixed in index space, so a
deformed 478-mesh just supplies new vertex positions. See
feat.plotting.plot_face_regions.
Source code in feat/utils/region_maps.py
triangle_adjacency(tris)
¶
{triangle_index: [neighbour triangle indices]} — triangles sharing an
edge (two vertices).