Eyebrow detector
How a raised eyebrow becomes a select.
The detector is in src/renderer/gestures/brow.ts. It takes one brow-ratio sample at a time and returns true once per raise.
The signal
The ratio is the distance from eyebrow to upper eyelid, divided by the distance between the outer eye corners. Dividing by eye spacing means moving closer to the camera does not change it. It uses landmarks 105 and 334 (eyebrows), 159 and 386 (eyelids), and 33 and 263 (eye corners).
How it decides
Smooth
Raw face-mesh brow height jitters by about ±10% between frames, so it is smoothed first.
Compare with a personal baseline
The baseline follows your resting position over a few seconds, and only updates while your eyebrows are down.
Fire on a held rise
Above 28% over the baseline for 200 ms, it fires.
Wait for a relax
It re-arms only after the ratio drops below 10% over the baseline, so one long raise cannot select twice.
Samples more than double the baseline are dropped as tracking glitches. One appeared in the first long recording.
Results
On the recording: 2 of 3 cued raises, 0 false selects. The third was missed because the eyebrows stayed up after the second raise: the ratio never dropped below the re-arm line before that cue ended. Its time above the fire line was also too brief to pass the hold.
Options and defaults are listed in Detector options.