Tuning Identification
Identification quality is a chain: camera image, face detection, template matching against a threshold, liveness and quality gates, and the enrolled reference. Tune it in that order. No threshold rescues a camera that delivers small, backlit faces, and no camera compensates for a bad enrollment photo. Default values and what they mean are in Detection and Matching Settings and Accuracy and Thresholds; this page is the method.
Tune in this order
| Step | What to check | Where |
|---|---|---|
| 1. Camera | Eye distance 50 px or more at the recognition point, frontal angles, no backlight, 15 fps or more | Camera Selection and Placement |
| 2. Detection | Minimum and maximum face size, detection confidence, redetection interval; too loose floods the matcher with junk, too strict drops real faces | Camera Settings Reference |
| 3. Threshold | Match score 0-100 compared to each watchlist's threshold (default 40) | Manage Watchlists |
| 4. Liveness and quality gates | Distant and Nearby liveness thresholds; whether liveness runs on matched faces only | Liveness |
| 5. Enrollment | Frontal, sharp, well-lit references; no duplicates or stale records | Enrollment Image Quality |
Measure before you touch anything
Your instrument is the ratio of matches to no-matches per camera over a comparable time window, together with the score distribution of the matches. Two ways to get it:
- Station: the event history lists matched and unmatched faces per camera with their scores and liveness results; filter by camera and time and note how known people score.
- GraphQL: query stored results on
http://localhost:8097/graphql, or subscribe tomatchResultandnoMatchResultand count live (GraphQL API).
query {
matchResults(where: { createdAt: { gte: "2026-09-01T00:00:00Z" } }) {
items { createdAt streamId watchlistDisplayName watchlistMemberDisplayName score }
}
}
Walk a set of enrolled people through each camera several times, then look at where genuine scores cluster and how far above the threshold they sit. If genuine walk-throughs score close to the threshold, fix the camera or the enrollment before moving the threshold.
Thresholds: the false-accept / false-reject trade
The threshold is set per watchlist and expresses one trade-off: raising it means fewer false accepts and more genuine people falling into noMatchResult; lowering it clears more people at the cost of security margin. Start conservative on watchlists whose match triggers an action against the person (a wrong alert is expensive) and tune permissive watchlists against the observed genuine scores from your own site. Station also shows a percentage next to the score, a linear conversion configured in .env.station; tune on the raw score, not the percentage.
Liveness and quality gates
Passive liveness (Distant for people walking towards the camera, Nearby for faces close to it) and the detection quality settings act as gates before or after matching. By default server-side liveness runs on matched faces only (SpoofDetection__SkipUnidentified=true in .env). Stricter liveness thresholds protect against presentation attacks but reject more genuine people, and a sudden rise in liveness failures on one camera usually means a physical change (new lighting, WDR switched on, a reflective surface) rather than a parameter problem.
Enrollment quality matters as much
Match scores are only as good as the enrolled reference. If one person scores low on every camera, re-enroll them with a better image before blaming thresholds; if many people score low on one camera, it is the camera. Removing duplicate and outdated members keeps scores clean and matching fast.
Change one thing at a time
Change a single parameter, give it enough traffic to matter, measure again with the same method and window, and keep a log of what changed and when. Detection and threshold changes take effect immediately; camera and lighting changes need a fresh set of walk-throughs.