Higher-ranked models (ASFD-D6, TinaFace+TTA) achieve marginally better Hard AP but at 10-100× the compute cost , making them impractical for video.
Input Image (640×640)
│
▼
┌─────────────────────────────────────────┐
│ BACKBONE (NAS-searched ResNet-style) │
│ ┌─────┐ ┌─────┐ ┌──────┐ ┌─────┐ │
│ │Stem │→ │ S1 │→ │ S2 │→ │ S3 │→ │ S4 │
│ │s=4 │ │s=4 │ │ s=8 │ │s=16 │ │s=32 │
│ └─────┘ └─────┘ └──┬───┘ └──┬──┘ └──┬──┘
│ │ C3 │ C4 │ C5
└────────────────────────┼─────────┼────────┼──┘
│ │ │
┌────────────────────▼─────────▼────────▼──┐
│ PAFPN (Path Aggregation FPN) │
│ Top-down (FPN) + Bottom-up (PAN) │
│ ┌────┐ ┌────┐ ┌────┐ │
│ │ P3 │ ← │ P4 │ ← │ P5 │ (top-down) │
│ │ P3 │ → │ P4 │ → │ P5 │ (bottom-up) │
│ │s=8 │ │s=16│ │s=32│ │
│ └──┬─┘ └──┬─┘ └──┬─┘ │
└─────┼─────────┼─────────┼─────────────────┘
│ │ │
┌─────▼─────────▼─────────▼─────────────────┐
│ SHARED HEAD (per level, weight-shared) │
│ ┌──────────┐ ┌──────────┐ │
│ │ CLS (GFL)│ │ REG(DIoU)│ [LMK (opt)] │
│ │ A×1 │ │ A×4 │ [A×10] │
│ └──────────┘ └──────────┘ │
└───────────────────────────────────────────┘
│ │
▼ ▼
┌─────────────┐ ┌──────────────┐
│ ATSS Match │ │ NMS (θ=0.4) │
│ (training) │ │ (inference) │
└─────────────┘ └──────────────┘
Frame → Detector (SCRFD) → ByteTrack Tracker → Temporal Smoother → Output
↓ ↓ ↓
Per-frame boxes Track IDs (stable) Jitter-free boxes
+ scores + Kalman prediction + Score momentum
+ landmarks + 2-stage matching + Adaptive EMA
1 from facedet import VideoFaceDetector
2
3 detector = VideoFaceDetector (
4 model_path = 'checkpoints/scrfd_34g_best.pth' ,
5 model_name = 'scrfd_34g' ,
6 device = 'cuda' ,
7 use_tracking = True ,
8 use_smoothing = True ,
9 )
10
11 # Process video file
12 stats = detector . process_video (
13 source = 'input.mp4' ,
14 output_path = 'output.mp4' ,
15 show = True ,
16 )
17 # → {total_frames: 1200, avg_fps: 75.3, avg_faces_per_frame: 4.2}
1 from facedet import build_detector
2 import cv2 , torch
3
4 model = build_detector ( 'scrfd_34g' ) . cuda ( ) . eval ( )
5 # Load checkpoint...
6
7 img = cv2 . imread ( 'photo.jpg' )
8 # Preprocess... (see scripts/evaluate.py for full example)
9 results = model ( tensor )
10 # → [{'boxes': tensor([...]), 'scores': tensor([...])}]
1 python scripts/detect_video.py \
2 --model scrfd_2.5g \
3 --checkpoint checkpoints/scrfd_2.5g_best.pth \
4 --input 0 --show
data/wider_face/
├── WIDER_train/images/
├── WIDER_val/images/
├── wider_face_split/
│ ├── wider_face_train_bbx_gt.txt
│ └── wider_face_val_bbx_gt.txt
└── retinaface_gt/ (optional, for landmark training)
├── train/label.txt
└── val/label.txt
1 # Single GPU — SCRFD-34G (flagship)
2 python scripts/train.py \
3 --model scrfd_34g \
4 --data-root data/wider_face \
5 --epochs 640 \
6 --batch-size 8 \
7 --lr 0.01
8
9 # Multi-GPU — 4× V100
10 torchrun --nproc_per_node = 4 scripts/train.py \
11 --model scrfd_34g \
12 --data-root data/wider_face \
13 --epochs 640 \
14 --batch-size 8 \
15 --lr 0.01
16
17 # Real-time variant
18 python scripts/train.py \
19 --model scrfd_2.5g \
20 --data-root data/wider_face \
21 --epochs 640 \
22 --batch-size 16 \
23 --lr 0.02
1 python scripts/evaluate.py \
2 --model scrfd_34g \
3 --checkpoint checkpoints/scrfd_34g_best.pth \
4 --data-root data/wider_face \
5 --output-dir results/scrfd_34g \
6 --benchmark
1 python scripts/export.py \
2 --model scrfd_34g \
3 --checkpoint checkpoints/scrfd_34g_best.pth \
4 --output deploy/scrfd_34g.onnx \
5 --input-size 640
1 trtexec --onnx = deploy/scrfd_34g.onnx \
2 --saveEngine = deploy/scrfd_34g_fp16.engine \
3 --fp16 --workspace = 4096
1 from facedet . deploy import quantize_model
2 quantized = quantize_model ( model , method = 'dynamic' )
facedet/
├── README.md # This file
├── setup.py # Package installation
├── requirements.txt # Dependencies
│
├── models/ # Model architectures
│ ├── backbone.py # NAS-searched ResNet backbones
│ ├── neck.py # PAFPN feature pyramid
│ ├── head.py # Shared detection head (cls/reg/lmk)
│ ├── anchor.py # Anchor generation + ATSS matching
│ ├── losses.py # GFL, DIoU, Focal, Landmark losses
│ └── detector.py # Full SCRFD detector (train + inference)
│
├── data/ # Data pipeline
│ ├── widerface.py # WiderFace dataset loader
│ ├── augmentations.py # Training/val/robustness augmentations
│ └── dataloader.py # DataLoader builders
│
├── engine/ # Video inference engine
│ ├── video_detector.py # End-to-end video processing
│ ├── tracker.py # ByteTrack face tracker
│ └── temporal.py # Temporal EMA smoother
│
├── evaluation/ # Evaluation suite
│ ├── widerface_eval.py # WiderFace protocol (Easy/Med/Hard AP)
│ ├── speed_benchmark.py # Latency/throughput benchmarks
│ └── metrics.py # Core metrics (AP, IoU, recall)
│
├── deploy/ # Deployment
│ ├── export_onnx.py # ONNX export + verification
│ └── optimize.py # Quantization, TensorRT guide
│
├── configs/ # Configuration files
│ ├── scrfd_34g.yaml # Flagship (quality)
│ ├── scrfd_10g.yaml # Balanced
│ ├── scrfd_2.5g.yaml # Real-time
│ ├── scrfd_0.5g.yaml # Mobile
│ └── ablations.yaml # Ablation study configs
│
├── scripts/ # Entry points
│ ├── train.py # Training (single/multi-GPU)
│ ├── evaluate.py # WiderFace evaluation + speed bench
│ ├── detect_video.py # Video inference CLI
│ └── export.py # ONNX export CLI
│
└── utils/ # Helpers
├── visualization.py # Drawing utilities
└── io.py # Checkpoint I/O