Files
DarkRoom/models/face
dtourolle 4f31123b0c Let the user choose which SCRFD finds their faces
faces.md §12.3 measured what the cheapest detector costs: the small
faces in every group shot, and a dog embedded a dozen times. Which
trade is right depends on the machine doing the sweep — a desktop left
overnight and a tablet on a battery want different answers — so the
detector is now a per-device setting, Fast / Balanced / Thorough on
the settings page beside the indexing button, persisted with the rest
of the settings file.

A detector is half of a model id. Every face, marker, shard and
calibration is keyed on faces.model_id precisely so that a model change
is a new id and a re-index rather than a silent change under existing
data, and a detector change is a model change: it decides which faces
exist and where the landmarks that align them land. So each choice
names its own pipeline. 500M keeps the bare "w600k_mbf" every existing
library was written under, so an upgrade disturbs nothing; the others
are qualified. Choosing one restarts coverage from zero under the new
id, the sweep re-detects, confirmed names carry across by box overlap,
and the sync shards are keyed by the same id so a peer on another
setting neither adopts nor pollutes them. The library controller
carries the id into the sync the same way it carries the cache budget,
because the sync starts from places that have no settings in reach.

All three shape-fixed exports ship — APK, Arch, Flatpak — since a
tablet has no other way to obtain the one it was not installed with;
the APK grows by twenty megabytes for the choice.
2026-09-11 22:12:53 +02:00
..

Face models

The shape-fixed SCRFD detectors and the ArcFace/MobileFaceNet embedder, in LFS. One copy, packaged by every platform:

Platform How it ships Where it lands
Android assemble-apk.sh bundles them as APK assets; android_main unpacks on first launch the shared user data directory
Arch PKGBUILD installs them /usr/share/darkroom/models/

library::face_models searches the account's own directory, then the shared user directory, then $XDG_DATA_DIRS — so a pair the user placed by hand always outranks the packaged one.

scrfd_500m_640.onnx    2.5 MB   "Fast" in settings — what every library was indexed with until 0.12
scrfd_2.5g_640.onnx    3.3 MB   "Balanced" — 14% more faces for 12% more time (faces.md §12.3)
scrfd_10g_640.onnx      17 MB   "Thorough" — a further 12% for 3× the time
arcface_mbf_b1.onnx     13 MB

Which detector runs is a per-device setting (FaceSettings::detector); all three are installed so the choice exists on every platform. Each is its own faces.model_id, so changing it re-indexes.

A clone without git-lfs gets a ~130-byte pointer where each model should be. Both packagers check for exactly that and refuse, rather than shipping the pointer and failing inside tract on the user's machine. Fix it with git lfs pull.

These are not what InsightFace ships. They came from buffalo_sc.zip, buffalo_m.zip, buffalo_l.zip and buffalo_s.zip on the InsightFace v0.7 release with their input dimensions pinned, because tract cannot parse any of the graphs while they are dynamic:

./tools/fix-face-model-shapes.sh det_500m.onnx  models/face/scrfd_500m_640.onnx --input input.1=1,3,640,640
./tools/fix-face-model-shapes.sh det_2.5g.onnx  models/face/scrfd_2.5g_640.onnx --input input.1=1,3,640,640
./tools/fix-face-model-shapes.sh det_10g.onnx   models/face/scrfd_10g_640.onnx  --input input.1=1,3,640,640
./tools/fix-face-model-shapes.sh w600k_mbf.onnx models/face/arcface_mbf_b1.onnx --dim None=1

The weights carry a non-commercial research-only grant. They are here because this is a private repository and self-installed builds; they come back out before anything is published, and the restriction binds whoever uses the app, not only the project. docs/faces.md §2.2a is the decision.