swageswagehandshape practice

Concept & eval

The mechanism

Every prediction runs the same seven-step pipeline, live, in your browser — the exact code trainer and browser share (src/lib/normalize.ts) so they can never quietly drift apart:

normalize.ts + classifier.ts pipelineTwenty-one raw hand landmarks are mirrored to a canonical right hand, translated so the wrist is the origin, scaled by the wrist-to-middle-knuckle distance, and rotated to a fixed angle, producing a 63-dimensional vector. A small MLP (63 to 48 to 24) turns that vector into a letter, shown in amber once the prediction is held stable.21 raw landmarksmirror (L→R)translatescalerotate63-dim vectorMLP (48 hidden)held letter

MediaPipe's Hand Landmarker outputs 21 (x, y, z) points per hand. A left hand is mirrored onto a canonical right hand, the wrist becomes the coordinate origin, the whole hand is scaled so the wrist-to-middle-knuckle distance is 1 (invariant to hand size and camera distance), and the hand is rotated so that same reference point lands at a fixed angle (invariant to how the hand is tilted in-plane — see Limitations for what this does not correct). The resulting 63 numbers feed a tiny neural network — Dense(48, relu) then Dense(24, softmax), about 4,200 parameters, <50KB committed as JSON — that outputs a letter and a confidence. A held-stable prediction (SPEC.md §7.1: 6 of the last 8 frames agreeing at ≥0.9 confidence) fires once, shown in amber above.

Split policy

SplitSourcePurpose
trainasl-now community pool (MIT), J/Z folders excludedmodel fitting
val1 self-collected signer, never in trainthreshold tuning, early stopping
test1 different self-collected signer, never in train or valthe published numbers, touched once

That is the design. What this build actually has: the asl-now pool's own signer composition is unverified — no such field exists in that dataset, so it is used for training only, never for published val/test numbers (matches the design above). The self-collected val/test signers do not exist yet in this repo — see the provisional banner above. The numbers below come from a random, file-level split of the asl-now pool itself, train=1312 / val=281 / test=281 samples — real numbers, honestly captioned, not the design's actual claim.

Per-letter precision / recall / F1

Test-set accuracy: 95.7% (281 samples). Ship bar is ≥70% on a genuine per-signer test set (SPEC.md §3.4) — not met, because the split above is provisional.

LetterPrecisionRecallF1Support
A11110
B0.833310.909110
C1118
D10.81820.911
E0.910.94749
F10.88890.94129
G0.86670.92860.896614
H11110
I11110
K10.90.947410
L11113
M10.92310.9613
N10.92310.9613
O11115
P11111
Q0.937510.967715
R10.81820.911
S0.857110.923112
T0.909110.952410
U0.941210.969716
V0.857110.923112
W11111
X10.8750.933316
Y10.91670.956512

Confusion matrix

Rows are the true letter, columns the predicted letter. The diagonal (correct predictions) is shaded; off-diagonal cells above 40% of this matrix's highest confusion count are highlighted in amber.

Confusion matrix: rows are the true letter, columns the predicted letter.
↓true \ pred→ABCDEFGHIKLMNOPQRSTUVWXY
A10
B10
C8
D191
E9
F18
G131
H10
I10
K91
L13
M121
N121
O15
P11
Q15
R911
S12
T10
U16
V12
W11
X214
Y111

Most confused pairs

Ranked by raw confusion count in the matrix above — this is exactly what Drill mode's "confusable" bias draws from (try it):

No J, no Z — by design, not by omission

24 classes, not 26: A B C D E F G H I K L M N O P Q R S T U V W X Y. Both excluded letters require traced motion a single held frame cannot see. More on Limitations.