Concepts
Choosing a face-match threshold: FMR, FNMR, and operating points
There is no universal magic number. Here's how to find the right one for your data.
TL;DR
A similarity threshold is a business decision, not a constant. Raising it lowers the false match rate (strangers wrongly matched) but raises the false non-match rate (real matches missed) — and vice versa. Pick it by running labelled positive and negative pairs from your own data, plotting the two error rates against the threshold, and choosing the operating point your use case can tolerate. Anyone who hands you a single universal number ("use 85%") is guessing.
Every face API returns a similarity score, and every team asks the same question: what score counts as a match? The honest answer is that it depends on your photos and the cost of each kind of error. Let's make that concrete.
The two errors you're trading off
| Term | What it means | Goes up when you… |
|---|---|---|
| False Match Rate (FMR) | Different people scored as the same person | …lower the threshold |
| False Non-Match Rate (FNMR) | The same person scored as different people | …raise the threshold |
You cannot minimize both at once. A signup verification step wants a low FMR (don't accept a mismatched selfie, even if it occasionally sends a real user to manual review). An event photo gallery tolerates a higher FMR behind a confirm step, because missing someone's photos is worse than showing one extra to confirm.
Note: Mind the score scale. SightRadar's native API returns a score on a 0–1 scale; AWS Rekognition's Similarity is 0–100. A threshold of 0.9 on SightRadar is not 90 on Rekognition unless you convert — always sweep on the scale your engine actually returns.
How to actually pick the number
- Build a validation set from your own consented images: pairs you know are the same person (positives) and pairs you know are different (negatives). Size it for the error rate you need to measure — a very low target FMR needs *many thousands* of negative pairs, because you can't measure a 1-in-10,000 rate with only a few hundred.
- Score every pair with the API's compare/search and record the similarity.
- Plot FMR and FNMR against threshold. You'll see two curves crossing — the shape is specific to your data (posed selfies and casual candids behave very differently).
- Choose the operating point by the cost of each error in your product, not by the crossover.
- For 1:N search, validate at gallery scale. Pairwise FMR understates false-identification risk when a probe is compared against thousands of faces — the chance of *some* wrong match grows with gallery size. Measure identification error against realistic gallery sizes, not just pair-at-a-time.
- Re-validate when your image mix or the model version changes.
# similarity is SightRadar's native 0-1 score, so sweep 0.00..0.99.
# (On AWS Rekognition, Similarity is 0-100 — sweep 0..100 instead.)
def sweep(pairs): # pairs: [(similarity, is_same_person), ...]
neg = sum(1 for _, same in pairs if not same) or 1
pos = sum(1 for _, same in pairs if same) or 1
for i in range(0, 100):
t = i / 100
fm = sum(1 for s, same in pairs if s >= t and not same)
fnm = sum(1 for s, same in pairs if s < t and same)
print(f"t={t:.2f} FMR={fm/neg:.4f} FNMR={fnm/pos:.4f}")The two-tier reveal pattern
For 1:N search (find-my-photos), you don't need a single line. Use two: an auto threshold high enough to reveal immediately, and a lower review threshold whose matches are shown behind a "confirm it's you" step. This gives high recall without auto-revealing a stranger's photos to the wrong person. SightRadar labels each match auto or review for exactly this; a client that ignores the label sees every match as auto.
Tip: Scores are not comparable across engines. A threshold tuned on AWS Rekognition will not mean the same thing on another API — re-run the sweep after any migration.
See how SightRadar returns calibrated scores and auto/review tiers.
Read the API referenceFrequently asked questions
What is a good similarity threshold for face recognition?
There is no universal number. The right threshold depends on your image quality and the relative cost of a false match versus a missed match. Build a validation set of same-person and different-person pairs from your own data, sweep the threshold while measuring false match rate (FMR) and false non-match rate (FNMR), and pick the operating point your use case tolerates. A door lock wants very low FMR; a photo gallery can tolerate higher FMR behind a confirmation step.
What's the difference between FMR and FNMR?
False Match Rate (FMR) is how often different people are scored as the same person; it rises as you lower the threshold. False Non-Match Rate (FNMR) is how often the same person is scored as different people; it rises as you raise the threshold. You trade one against the other — you cannot minimize both simultaneously.
Can I reuse my AWS Rekognition threshold on another API?
No. Similarity scores are engine-specific and not directly comparable across providers, so a threshold tuned on one API will not mean the same thing on another. Re-run your FMR/FNMR sweep on the new engine after migrating.