fix(sound): concert advance via body wrists
CI build oscope-of / build-check (push) Has been cancelled

The hand-based arms-crossed gesture could never fire: hand L/R is
position-sorted (rx>=lx always), and at full-body distance MediaPipe
doesnt detect the hands at all (crossing also occludes them). Detect
the advance from the body wrists instead: new /pose/wrist OSCdef ->
~poseWrist, and detectCross fires when the right wrist swaps clearly
left of the left wrist (a clear X), performer centered, wrists at chest
height. Verified headless (wrist-cross advance 1->2).
This commit is contained in:
L'électron rare
2026-06-27 17:48:23 +02:00
parent 1cd8c2e259
commit 883ada7d61
2 changed files with 23 additions and 7 deletions
+12
View File
@@ -495,6 +495,7 @@ OSCdef(\poseLeave, { |msg|
~poseState.removeAt(pid);
~poseKin.removeAt(pid);
~poseCenter.removeAt(pid);
~poseWrist !? { ~poseWrist.removeAt(pid) };
}, '/pose/leave');
OSCdef(\poseHands, { |msg|
@@ -509,6 +510,17 @@ OSCdef(\poseHands, { |msg|
~handFeat[\dist] = msg[10];
}, '/pose/hands');
// Body wrists (skeleton, tracked even when hands are occluded/too small).
// /pose/wrist <pid> <l|r> <x> <y> (anatomical L/R from MediaPipe pose)
~poseWrist = ~poseWrist ? Dictionary.new;
OSCdef(\poseWrist, { |msg|
var pid = msg[1].asInteger;
var e = ~poseWrist[pid] ? ();
if(msg[2].asString[0] == $l) { e[\lx] = msg[3]; e[\ly] = msg[4]; }
{ e[\rx] = msg[3]; e[\ry] = msg[4]; };
~poseWrist[pid] = e;
}, '/pose/wrist');
~poseCenter = ~poseCenter ? Dictionary.new;
OSCdef(\poseCenter, { |msg|
var pid = msg[1].asInteger;
+11 -7
View File
@@ -57,13 +57,17 @@
// geste bras-croises : main D a gauche de main G, a mi-hauteur, maintenu
~concert[\detectCross] = { |pose, now|
var hf = pose[\hands];
var ry = (hf[\ry] ? 0); var ly = (hf[\ly] ? 0);
var crossed = pose[\hasBody] and: {
((hf[\rx] ? 0.5) < ((hf[\lx] ? 0.5) - 0.08))
and: { (ry >= 0.25) and: { ry <= 0.75 } }
and: { (ly >= 0.25) and: { ly <= 0.75 } }
};
// Detect via BODY WRISTS (skeleton), not hands: at full-body distance the
// hands aren't detected and crossing occludes them. Clear X cross = the
// right wrist swaps to the LEFT of the left wrist. Require the performer
// centered (not at a frame edge) + wrists at chest height.
var w = (~poseWrist.notNil.if({ ~poseWrist.values.detect({ |v| v.notNil }) })) ? ();
var lx = (w[\lx] ? 0.5); var rx = (w[\rx] ? 0.5);
var ly = (w[\ly] ? 0.5); var ry = (w[\ry] ? 0.5);
var centered = (lx > 0.15) and: { lx < 0.85 } and: { rx > 0.15 } and: { rx < 0.85 };
var midH = (ly > 0.2) and: { ly < 0.85 } and: { ry > 0.2 } and: { ry < 0.85 };
var crossed = pose[\hasBody] and: { centered } and: { midH }
and: { rx < (lx - 0.10) };
if(crossed) {
if(~concert[\crossT] <= 0) { ~concert[\crossT] = now };
if(((now - ~concert[\crossT]) >= ~ccCrossHold)