Spaces:
Sleeping
Sleeping
Commit ·
623fcd9
1
Parent(s): 79a823e
Fix affect and gesture misclassification
Browse files- Lower HAPPY LCP threshold 0.015 → 0.008 so smiles register
- Raise EMA alpha 0.3 → 0.4 for faster affect response
- Stricter fingersCurled check (0.85×) to prevent borderline pointing from satisfying thumb curl
- Check POINTING before THUMBS_UP so raised-thumb pointing fires correct label
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
frontend/src/hooks/useSensing.ts
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
| 15 |
} from "../lib/sensing";
|
| 16 |
import { DEFAULT_AIR_TEMPLATES } from "../lib/airTemplates";
|
| 17 |
|
| 18 |
-
const EMA_ALPHA = 0.
|
| 19 |
|
| 20 |
export function useSensing() {
|
| 21 |
const faceLandmarkerRef = useRef<FaceLandmarker | null>(null);
|
|
|
|
| 15 |
} from "../lib/sensing";
|
| 16 |
import { DEFAULT_AIR_TEMPLATES } from "../lib/airTemplates";
|
| 17 |
|
| 18 |
+
const EMA_ALPHA = 0.4;
|
| 19 |
|
| 20 |
export function useSensing() {
|
| 21 |
const faceLandmarkerRef = useRef<FaceLandmarker | null>(null);
|
frontend/src/lib/sensing.ts
CHANGED
|
@@ -19,8 +19,7 @@ export function classifyAffect(v: AffectVector): Affect {
|
|
| 19 |
// FRUSTRATED: a clear frown, OR brows lowered + squinting — either signals displeasure
|
| 20 |
if (v.LCP < -0.015) return "FRUSTRATED";
|
| 21 |
if (v.BRI > -0.2 && v.EAR < 0.18) return "FRUSTRATED";
|
| 22 |
-
|
| 23 |
-
if (v.LCP > 0.015) return "HAPPY";
|
| 24 |
return "NEUTRAL";
|
| 25 |
}
|
| 26 |
|
|
@@ -105,21 +104,25 @@ export function classifyGesture(landmarks: Point3D[]): GestureName | null {
|
|
| 105 |
const pinkyTip = p[20];
|
| 106 |
const indexMcp = p[5];
|
| 107 |
|
|
|
|
|
|
|
| 108 |
const fingersCurled = [
|
| 109 |
[indexTip, p[5]],
|
| 110 |
[middleTip, p[9]],
|
| 111 |
[ringTip, p[13]],
|
| 112 |
-
].every(([tip, mcp]) => norm3(tip) < norm3(mcp));
|
| 113 |
-
|
| 114 |
-
if (thumbTip.y < -0.3 && fingersCurled) return "THUMBS_UP";
|
| 115 |
-
if (thumbTip.y > 0.3 && fingersCurled) return "THUMBS_DOWN";
|
| 116 |
|
|
|
|
|
|
|
| 117 |
const indexExtended = norm3(indexTip) > norm3(indexMcp) * 1.3;
|
| 118 |
const othersCurled = [middleTip, ringTip, pinkyTip].every(
|
| 119 |
(tip) => norm3(tip) < 0.5
|
| 120 |
);
|
| 121 |
if (indexExtended && othersCurled) return "POINTING";
|
| 122 |
|
|
|
|
|
|
|
|
|
|
| 123 |
const allExtended = [indexTip, middleTip, ringTip, pinkyTip].every(
|
| 124 |
(tip) => norm3(tip) > 0.5
|
| 125 |
);
|
|
|
|
| 19 |
// FRUSTRATED: a clear frown, OR brows lowered + squinting — either signals displeasure
|
| 20 |
if (v.LCP < -0.015) return "FRUSTRATED";
|
| 21 |
if (v.BRI > -0.2 && v.EAR < 0.18) return "FRUSTRATED";
|
| 22 |
+
if (v.LCP > 0.008) return "HAPPY";
|
|
|
|
| 23 |
return "NEUTRAL";
|
| 24 |
}
|
| 25 |
|
|
|
|
| 104 |
const pinkyTip = p[20];
|
| 105 |
const indexMcp = p[5];
|
| 106 |
|
| 107 |
+
// Require tip to be meaningfully closer to wrist than MCP (0.85×), not just barely under —
|
| 108 |
+
// prevents borderline pointing poses from satisfying the curl check.
|
| 109 |
const fingersCurled = [
|
| 110 |
[indexTip, p[5]],
|
| 111 |
[middleTip, p[9]],
|
| 112 |
[ringTip, p[13]],
|
| 113 |
+
].every(([tip, mcp]) => norm3(tip) < norm3(mcp) * 0.85);
|
|
|
|
|
|
|
|
|
|
| 114 |
|
| 115 |
+
// Check POINTING before THUMBS_UP — pointing with a raised thumb would otherwise
|
| 116 |
+
// satisfy fingersCurled on a noisy frame and fire the wrong label first.
|
| 117 |
const indexExtended = norm3(indexTip) > norm3(indexMcp) * 1.3;
|
| 118 |
const othersCurled = [middleTip, ringTip, pinkyTip].every(
|
| 119 |
(tip) => norm3(tip) < 0.5
|
| 120 |
);
|
| 121 |
if (indexExtended && othersCurled) return "POINTING";
|
| 122 |
|
| 123 |
+
if (thumbTip.y < -0.3 && fingersCurled) return "THUMBS_UP";
|
| 124 |
+
if (thumbTip.y > 0.3 && fingersCurled) return "THUMBS_DOWN";
|
| 125 |
+
|
| 126 |
const allExtended = [indexTip, middleTip, ringTip, pinkyTip].every(
|
| 127 |
(tip) => norm3(tip) > 0.5
|
| 128 |
);
|