Skip to content

fix(visaged): warm up with the IR emitter active so the first verify is not blown out - #104

Open
jeffshee wants to merge 1 commit into
sovren-software:mainfrom
jeffshee:fix/emitter-lit-warmup
Open

fix(visaged): warm up with the IR emitter active so the first verify is not blown out#104
jeffshee wants to merge 1 commit into
sovren-software:mainfrom
jeffshee:fix/emitter-lit-warmup

Conversation

@jeffshee

Copy link
Copy Markdown

What problem does this solve?

On a camera with an emitter quirk, the first verify after every daemon start fails. That is
the first sudo after boot, and after every resume, since visage-resume.service restarts
the daemon.

Cause: sensor auto-gain only adapts while streaming, drops in about two seconds when the
emitter saturates it, and rises slowly. The startup warmup streams with the emitter off,
so gain settles against ambient light; the first lit capture is then saturated white and the
detector sees nothing. The symptom is indistinguishable from a liveness failure in the logs
(displacement=0.0, the single-usable-frame fail-closed case).

Type

  • Bug fix

What this changes

spawn_engine activates the emitter before the warmup and runs the warmup as one continuous
capture_frames stream instead of N single-frame capture_frame calls, then deactivates it.
Gain settles against the emitter, and since nothing streams with the emitter off afterwards,
every later capture starts adapted.

VISAGE_WARMUP_FRAMES keeps its default of 4 but now counts usable frames (capture_frames
skips the strobe's unlit half). It was already read by the daemon and exposed by the NixOS
module; this adds its missing row to the operations guide's variable table.

Testing

A/B on Syntek 174f:11a8 (ThinkPad P14s Gen 4, quirk in #102), same starting state for both
(gain adapted to ambient, emitter off), reproducing each path's exact capture sequence and
recording the frames capture_frames(3) would hand to the detector:

Path First verify after start 3 s later
upstream warmup means [33, 255, 33] — silhouette, white-out, silhouette [208, 206, 172]
this change means [24, 24, 24] — face crisply lit

Running the daemon with this change on Fedora 44 (VISAGE_WARMUP_FRAMES=25): ready 3.3 s
after start, first verify after restart matches. cargo test --workspace passes.

Checklist

  • cargo fmt --all -- --check passes
  • cargo clippy --workspace -- -D warnings passes
  • cargo test --workspace passes
  • Commits are signed off (git commit -s) per the DCO
  • I have read CONTRIBUTING.md

Breaking changes

None. Cameras without a quirk behave as before (no emitter to activate). On quirked cameras
the warmup takes slightly longer for the same number, since unlit strobe frames no longer
count. Cameras with reset_on_close = true hold an fd open for the warmup's duration, as they
already do for each capture.

…is not blown out

Sensor auto-gain only adapts while streaming, drops in about two seconds
when a quirked emitter saturates it, and rises slowly afterwards. The
startup warmup streamed with the emitter off, so gain settled against
ambient light and the first capture after every daemon start — the first
sudo after boot or resume — was saturated white and failed detection.

Activate the emitter before the warmup and run it as one continuous
capture_frames stream. VISAGE_WARMUP_FRAMES now counts usable frames (the
strobe's unlit half is skipped) and is documented; 25 works well on the
camera below.

Measured A/B on Syntek 174f:11a8, same starting state (gain adapted to
ambient, emitter off), reproducing each path's exact capture sequence:

  unfixed  first verify: detector gets frame means [33, 255, 33]
           (silhouette, white-out, silhouette); 3 s later [208, 206, 172]
  fixed    first verify: detector gets [24, 24, 24], face crisply lit

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Jeff Shee <jeffshee8969@gmail.com>
jeffshee added a commit to jeffshee/visage that referenced this pull request Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant