feat(pose): wrist-anchored xy mods + wrist markers
CI build oscope-of / build-check (push) Has been cancelled
CI build oscope-of / build-check (push) Has been cancelled
The X/Y voice mods were anchored to the 21-landmark centroid, so opening or pinching the fingers shifted the mod values (gesture/mod cross-talk). cx/cy now track the WRIST (kp 0). The renderer draws a cross marker at each wrist on the video whenever features exist, so the control point stays visible even for far hands the overlay filters out (user request live 2026-07-02).
This commit is contained in:
@@ -62,8 +62,12 @@ class HandFeatureExtractor:
|
||||
def _features(self, lm: list) -> dict:
|
||||
xs = [_finite(_coord(p, "x", 0), 0.5) for p in lm[:21]]
|
||||
ys = [_finite(_coord(p, "y", 1), 0.5) for p in lm[:21]]
|
||||
cx = _clamp(sum(xs) / len(xs), 0.0, 1.0)
|
||||
cy = _clamp(sum(ys) / len(ys), 0.0, 1.0)
|
||||
# cx/cy anchor = the WRIST (kp 0), not the landmark centroid: the
|
||||
# centroid shifts when fingers open/pinch, cross-talking gestures
|
||||
# into the X/Y voice mods. The wrist decouples them (user request
|
||||
# live 2026-07-02).
|
||||
cx = _clamp(xs[WRIST], 0.0, 1.0)
|
||||
cy = _clamp(ys[WRIST], 0.0, 1.0)
|
||||
size = math.hypot(xs[MIDDLE_MCP] - xs[WRIST], ys[MIDDLE_MCP] - ys[WRIST])
|
||||
size = size if size > 1e-4 else 1e-4
|
||||
span = math.hypot(xs[THUMB_TIP] - xs[PINKY_TIP],
|
||||
|
||||
@@ -575,6 +575,16 @@ class MetalRenderer(NSObject):
|
||||
content_pid=pid_s,
|
||||
):
|
||||
push_panel(ax, ay, bx, by, gconf, gpid)
|
||||
# Wrist marker ON the video: the X/Y voice mods are anchored
|
||||
# to the wrist, so its control point stays visible whenever
|
||||
# features exist (even for far hands the overlay filters
|
||||
# out). push_seg applies the video mirror like the overlay.
|
||||
if _g_cx is not None and _g_cy is not None:
|
||||
_mx = 0.015 / asp
|
||||
push_seg(_g_cx - _mx, _g_cy, _g_cx + _mx, _g_cy,
|
||||
1.0, pid_s)
|
||||
push_seg(_g_cx, _g_cy - 0.015, _g_cx, _g_cy + 0.015,
|
||||
1.0, pid_s)
|
||||
if h_kp is not None:
|
||||
for seg in panel_segments(
|
||||
h_kp, side_name, lhand_bones_p, asp,
|
||||
|
||||
Reference in New Issue
Block a user