screenpad-runs

Training runs and weights for screenpad, a screen-replay presentation attack detector for face images (does an image show a live person, or a face on a screen photographed by a phone?). Code, report and inference: the screenpad repository; start with its README.

The detectors were trained with no real attacks: a physics-based simulator turns bona fide faces into synthetic screen recaptures, and camera-only controls make the screen the only difference to learn.

Which runs make up the shipped systems

System Members (runs in this repo)
Deployed (artefacts/frozen_photo.json, the default) H_dinov2b_loose224_photo_s42/43/44, I_dinov2b_loose392_photo_s42/43/44, PatchCore pc_loose224_b8_ftH
Initial (artefacts/frozen.json) A_dinov2b_loose224_s42/43/44, C_dinov2b_loose392_s42/43/44, PatchCore pc_loose224_b8_ftA

H and I are DINOv2-B (vit_base_patch14_dinov2.lvd142m) fine-tuned on loose face crops at 224 and 392 px with photometric augmentation; A and C are the same recipes without it. Held-out test (17 real attacks, 194 bona fide): both systems accept 1/17 attacks; the deployed system has AUC 0.988 and is far more robust to noise and blur, at a higher clean bona fide rejection (9.8% against 5.2%) at the shared calibration threshold.

Using the weights

You do not need to download anything by hand: screenpad infer (or screenpad fetch-models) downloads exactly the files the chosen system needs, and the Docker image does the same into a volume. Loading one classifier yourself:

import timm, torch
from huggingface_hub import hf_hub_download

ckpt = hf_hub_download("Jamie1701/screenpad-runs", "runs/H_dinov2b_loose224_photo_s42/ckpt/last.pt")
model = timm.create_model("vit_base_patch14_dinov2.lvd142m", pretrained=False, num_classes=1, img_size=224)
model.load_state_dict(torch.load(ckpt, map_location="cpu", weights_only=True))

Inputs must be prepared as screenpad does it (metadata-stripped load, YuNet face detection, eye-aligned 1.25 x face-box crop); raw scores are only meaningful after the per-member calibration stored in the ensemble files.

Layout of a run folder

File Contents
config.yaml the resolved training configuration
ckpt/last.pt weights used by the ensembles (last epoch); ckpt/best.pt is the best synthetic-validation checkpoint (not used)
metrics.csv, summary.json, train.log per-epoch metrics, final summary, training log
scores_last.csv, scores_best.csv per-image scores on validation and development images
provenance.json, SOURCE_DIFF.patch package versions, GPU, data hashes and the exact code state of the run
MANIFEST.json size and SHA-256 of every file, checked after upload

PatchCore runs (pc_*) hold a bank.pt memory bank (patch features of bona fide images) built on a fine-tuned run's backbone; one-class experiments (pc_*, ead_*, ssl_*) are reported in the technical report. Runs prefixed _ are pipeline smoke tests.

Licence and data

The weights were trained on images derived from FFHQ (CC BY-NC-SA 4.0), so they are released for non-commercial research use under the same terms. Backbones: DINOv2 (Apache-2.0), via timm (Apache-2.0). The screen-attack images used for evaluation belong to the assessors and are not included. Out of scope: prints, masks, deepfakes, injection attacks, and any standalone decision about a person.

Downloads last month
-
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support