Skip to Content

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.

Raise 1: firedRaise 2: firedRaise 3: no fire0%10%Re-arm line +10%28%Fire line +28%Resting baselineFired at 76.3 s, +32.4%Fired 76.3 sFired at 80.4 s, +31.6%Fired 80.4 sPeak +31.6% while not armed+31.6%, not armedRe-armed 86.2 sarmedarmedarmednot armednot armed72747678808284868890Seconds into the recording. Vertical axis: smoothed brow ratio above baseline.
One recorded session of one person. The detector fired on 2 of 3 cued raises, at 76.3 s and 80.4 s. Between raises 2 and 3 the smoothed ratio stayed between +10.9% and +28.9%, never below the +10% re-arm line, so the detector was not armed during raise 3 (peak +31.6%) and re-armed only at 86.2 s, after the cue ended. No stretch above the fire line in that raise lasted the 200 ms hold either; the longest was 132 ms.

Options and defaults are listed in Detector options.

On this page