Skip to content

Three-skinned realtime demo — needs better head / face tracking fidelity #583

Description

@ruvnet

Spinoff from the cinematic three.js skinned-realtime demo branch (feat/three-skinned-realtime-pose-demo / PR pending). Limbs + torso + hips all tracking well now; head movement is the next fidelity ceiling.

What's already shipped

examples/three.js/helpers-skinned-realtime.html — webcam → MediaPipe Pose Heavy → poseWorldLandmarks → direct quaternion retargeting onto a Mixamo X Bot. Live ESP32-S3 CSI over WebSocket from ruvultra (Tailscale).

Pipeline stage Working today
Camera 1280×720 @ 30 fps
Pose model MediaPipe Pose Heavy (modelComplexity=2), poseWorldLandmarks real meters
Retargeting 12 bones (arms × 2, legs × 2, spine × 3, neck) + Hips root rotation from shoulder/hip basis
Smoothing One Euro Filter per landmark per axis (minCutoff=1.7, beta=0.007)
Visibility gate per-bone slerp gain ramps vis 0.4 → 0.7
CSI overlay live ESP32-S3 (D0:CF:13:44:01:84) via ruvultra-csi-bridge.py systemd unit on ruvultra:8766

Why head movement specifically falls short

MediaPipe Pose's 33 landmarks only give:

  • 0 nose
  • 1–10 face/eyes/ears/mouth (low-fidelity, single point each)

The current Neck bone retarget uses shoulder_mid → ear_mid (kp 11/12 → 7/8). That's enough to drive the cervical-spine tilt, but:

  • The Head bone itself is not retargeted — head rotation around the neck pivot (look left/right, nod) is not captured
  • Ears have higher visibility than the nose but aren't reliable enough for full yaw/pitch/roll
  • No facial expression (mouth open, eyebrows, etc.)
  • No gaze direction

Candidate fixes

Option A — Add Head bone retarget from current landmarks

  • Head aimed at nose (kp 0), with the existing forward-bias-removal trick (project out the rest forward component)
  • Tracks yaw / pitch from nose displacement vs ear-midpoint
  • Cheap: no new model, no extra inference cost
  • Limited: no roll, no face expression

Option B — Upgrade to MediaPipe Holistic

  • Replaces Pose with Holistic: 33 pose landmarks + 468 face mesh + 21 left-hand + 21 right-hand
  • Drop-in API change: new Holistic() instead of new Pose(), results expose poseLandmarks + faceLandmarks + leftHandLandmarks + rightHandLandmarks
  • Face mesh gives proper head pose via PnP solver (3 axes of rotation, not just 1)
  • Hands give finger curl tracking — Mixamo X Bot has 20 finger bones per side already in mixamorigLeftHandIndex1 etc.
  • Cost: ~25 MB extra model download, ~30% more CPU per inference
  • Biggest fidelity jump available without a custom training pipeline

Option C — MediaPipe Face Mesh as a sidecar pipeline

  • Keep Pose Heavy for body, add @mediapipe/face_mesh separately
  • Run both in parallel, solve head pose from face mesh
  • More wiring than Holistic but lets us tune them independently

Option D — Solve head pose with cv2.solvePnP equivalent using just the kp 0..10 anchors

  • Use OpenCV.js or a pure-JS PnP solver
  • Inputs: nose, eyes, ears, mouth corners (6 stable face anchors)
  • Output: 3D head rotation matrix
  • Drives Head bone directly
  • Middle ground — better than just ear-midpoint, simpler than Holistic

Recommended next step

Option B (Holistic) for the biggest user-visible jump. Hands tracking is the second-most-asked-for feature after head, and Holistic gives both for free. The current helpers-skinned-realtime.html retargeting layer is shape-compatible — RETARGETS would just gain entries for LeftHandIndex1RightHandPinky3 (already valid Mixamo bone names, confirmed in the rig).

If Holistic feels too heavy on first-load (25 MB), gate it behind ?holistic=1 and keep Pose Heavy as the default.

Acceptance criteria

  • Looking left/right rotates the model's Head bone visibly through its full ~80° range
  • Nodding pitches the head up/down clearly, independent of torso lean
  • Head roll (tilting an ear toward a shoulder) reads on the rig
  • No false head motion when standing neutrally (rest pose holds)
  • (Stretch, Option B) Finger curls tracked when raising a hand near camera

Refs

🤖 Generated with claude-flow

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions