{
  "name": "Neetix Liveliness LFW View-2 face-verification benchmark",
  "description": "1:1 face-verification error curves (EER, FMR, FNMR) measured on the Labeled Faces in the Wild (LFW) View-2 protocol — 6,000 pairs, engine-side detect + align, 512-d cosine matching. Compares a fully commercially-licensable stack (YuNet + AdaFace, MIT/Apache-2.0) against a research-only baseline (InspireFace Megatron). Every number is reproducible with the public harness. Not a certification and not a claim of state-of-the-art accuracy.",
  "version": "1.0",
  "datePublished": "2026-08-30",
  "dateModified": "2026-08-30",
  "license": "CC-BY-4.0",
  "licenseUrl": "https://creativecommons.org/licenses/by/4.0/",
  "creator": {
    "name": "Neetix",
    "url": "https://liveliness.neetix.in"
  },
  "canonicalUrl": "https://liveliness.neetix.in/benchmarks/",
  "harnessRepository": "https://github.com/neetixai/liveness-benchmark",
  "source": "Figures mirror EVAL.md in the neetixai/liveliness-api repository. Python results produced by scripts/clean_swap_bench.py (onnxruntime); Rust-port results produced by the clean backend via `LV__ENGINE__BACKEND=clean ./target/release/eval`. No commit hash is pinned here because the harness dataset (LFW) is provisioned on the runner, not committed.",
  "protocol": {
    "dataset": "Labeled Faces in the Wild (LFW), View-2 (10-fold verification protocol)",
    "datasetOrigin": "University of Massachusetts, Amherst — http://vis-www.cs.umass.edu/lfw/ . Pairs/images retrieved via scikit-learn's md5-verified figshare mirrors.",
    "pairsTotal": 6000,
    "pairsGenuine": 3000,
    "pairsImpostor": 3000,
    "inputs": "Non-funneled original LFW images (no pre-aligned/pre-cropped inputs).",
    "alignment": "Engine-side face detection + landmark alignment, identical to the production pipeline.",
    "matching": "Cosine similarity between 512-d embeddings.",
    "metrics": ["EER", "FMR", "FNMR", "detect/align failure count"]
  },
  "runs": [
    {
      "id": "clean-rust-2026-08-30",
      "date": "2026-08-30",
      "label": "Clean license-safe stack — Rust port (headline)",
      "stack": "YuNet (OpenCV Zoo) detect + align, AdaFace IR-50 / WebFace4M embeddings, flip test-time augmentation, 2.0x-capped cubic-letterbox detect upscale; run via tract.",
      "license": "MIT + Apache-2.0",
      "harness": "LV__ENGINE__BACKEND=clean ./target/release/eval",
      "eerPct": 3.05,
      "eerThresholdCosine": 0.126,
      "detectFailures": 0,
      "pairsScored": 6000,
      "fmrZeroAtCosineGte": 0.28,
      "fnmrAtCosine0_32Pct": 3.67,
      "note": "Re-verification of the clean stack in the shipped Rust engine. Beats both the Python clean-stack run (3.33%) and prod Megatron (3.23%, which skipped 19 pairs). Per-pair parity vs the Python harness: median absolute cosine difference 0.002."
    },
    {
      "id": "clean-adaface-ir50-python-2026-08-30",
      "date": "2026-08-30",
      "label": "Clean license-safe stack — Python harness",
      "stack": "AdaFace IR-50 / WebFace4M + YuNet align, flip test-time augmentation, 2x detect upscale.",
      "license": "MIT + Apache-2.0",
      "harness": "scripts/clean_swap_bench.py",
      "eerPct": 3.33,
      "eerThresholdCosine": 0.122,
      "fnmrAtFmr0_1Pct": 3.67,
      "detectFailures": 0,
      "pairsScored": 6000,
      "maxImpostorCosine": 0.284,
      "fmrZeroAtCosineGte": 0.29
    },
    {
      "id": "clean-adaface-ir101-python-2026-08-30",
      "date": "2026-08-30",
      "label": "AdaFace IR-101 / WebFace12M, same pipeline",
      "stack": "AdaFace IR-101 / WebFace12M + YuNet align, flip TTA, 2x detect upscale.",
      "license": "MIT",
      "harness": "scripts/clean_swap_bench.py",
      "eerPct": 3.30,
      "eerThresholdCosine": 0.107,
      "fnmrAtFmr0_1Pct": 3.63,
      "detectFailures": 0,
      "pairsScored": 6000,
      "note": "IR-101 adds nothing measurable over IR-50 here (scores correlate 0.994); the LFW protocol floor is reached. IR-50 is shipped: half the size (174 MB ONNX) and ~2x faster."
    },
    {
      "id": "megatron-python-2026-08-30",
      "date": "2026-08-30",
      "label": "InspireFace Megatron (current prod, re-scored on the clean harness)",
      "stack": "InspireFace Megatron pack (ResNet-18 ArcFace, Glint360K).",
      "license": "research-only",
      "harness": "scripts/clean_swap_bench.py",
      "eerPct": 3.23,
      "eerThresholdCosine": 0.146,
      "fnmrAtFmr0_1Pct": 4.22,
      "detectFailures": 19,
      "pairsScored": 5981,
      "note": "Research-only license — the reason for the clean-stack swap. Skipped its 19 hardest pairs; the clean stack scored all 6,000."
    },
    {
      "id": "adaface-ir50-plain-yunet-2026-08-30",
      "date": "2026-08-30",
      "label": "AdaFace IR-50, plain YuNet align (no TTA / upscale)",
      "stack": "AdaFace IR-50 + plain YuNet align.",
      "license": "MIT",
      "harness": "scripts/clean_swap_bench.py",
      "eerPct": 4.90,
      "fnmrAtFmr0_1Pct": 5.53,
      "detectFailures": 0,
      "pairsScored": 6000,
      "note": "Ablation baseline. Flip-TTA + running YuNet on a 2x-upscaled image (sharper landmarks on small faces) is worth ~1.57 points — the wins were pipeline, not model."
    },
    {
      "id": "sface-yunet-2026-08-30",
      "date": "2026-08-30",
      "label": "SFace + YuNet",
      "stack": "SFace + YuNet align.",
      "license": "Apache-2.0",
      "harness": "scripts/clean_swap_bench.py",
      "eerPct": 5.50,
      "detectFailures": 0,
      "pairsScored": 6000
    },
    {
      "id": "adaface-ir50-mtcnn-2026-08-30",
      "date": "2026-08-30",
      "label": "AdaFace IR-50, MTCNN align (AdaFace repo's own eval path)",
      "stack": "AdaFace IR-50 + MTCNN align.",
      "license": "MIT",
      "harness": "scripts/clean_swap_bench.py",
      "eerPct": 6.34,
      "detectFailures": 39,
      "pairsScored": 5961,
      "note": "MTCNN alignment is WORSE than YuNet on 250px LFW originals — do not 'upgrade' the landmark source."
    },
    {
      "id": "megatron-2026-08-13",
      "date": "2026-08-13",
      "label": "InspireFace Megatron — first real-data run",
      "stack": "InspireFace v1.2.3 + Megatron pack (ResNet-18 ArcFace, Glint360K).",
      "license": "research-only",
      "harness": "./target/release/eval (native)",
      "eerPct": 3.26,
      "eerThresholdCosine": 0.145,
      "fnmrAtFmr1Pct": 3.48,
      "fnmrAtFmr0_1Pct": 4.22,
      "detectFailures": 19,
      "pairsScored": 5981,
      "maxImpostorCosine": 0.318,
      "fmrZeroAtCosineGte": 0.32,
      "thresholdSweep": [
        { "cosine": 0.40, "fnmrPct": 6.8, "fmrPct": 0.0 },
        { "cosine": 0.44, "fnmrPct": 9.4, "fmrPct": 0.0 },
        { "cosine": 0.48, "fnmrPct": 14.3, "fmrPct": 0.0 },
        { "cosine": 0.52, "fnmrPct": 20.5, "fmrPct": 0.0 },
        { "cosine": 0.56, "fnmrPct": 30.6, "fmrPct": 0.0 }
      ]
    }
  ],
  "caveats": [
    "LFW is a celebrity, largely non-Indian, near-frontal dataset. These figures say NOTHING about selfie-vs-Aadhaar matching, low light, aging, or Indian demographics. Do not treat them as KYC-grade accuracy.",
    "'0 observed false matches' is NOT '0% FMR'. With 0 of 3,000 impostor pairs matched, the 95% (Wilson / rule-of-three) upper bound on the true FMR is approximately 0.10%. Never quote a 0% FMR — KYC-grade FMR claims need millions of impostor pairs.",
    "~3% EER is an honest mid-pack result, not state of the art. Large modern proprietary packs report under 0.5% EER on LFW. We publish the real number rather than the best-looking one.",
    "No certification is claimed. Neetix holds no iBeta, NIST FRVT or FIDO certification for these results. Third-party PAD/accuracy testing is planned and will be published with dataset, protocol and demographic breakdown attached.",
    "These are 1:1 face-verification numbers, not liveness/PAD numbers. Presentation-attack metrics (APCER/BPCER per ISO/IEC 30107-3) are not measured by this protocol."
  ]
}
