Skip to content

Detection

Face detection is the first step in any face analysis pipeline. UniFace provides four detection models.


Available Models

Model Backbone Size Easy Medium Hard Landmarks
RetinaFace MobileNet V2 3.5 MB 91.7% 91.0% 86.6%
SCRFD SCRFD-10G 17 MB 95.2% 93.9% 83.1%
YOLOv5-Face YOLOv5s 28 MB 94.3% 92.6% 83.2%
YOLOv8-Face YOLOv8n 12 MB 94.6% 92.3% 79.6%

Dataset

All models trained on WIDERFACE dataset.


RetinaFace

Single-shot face detector with multi-scale feature pyramid.

Basic Usage

from uniface import RetinaFace

detector = RetinaFace()
faces = detector.detect(image)

for face in faces:
    print(f"Confidence: {face.confidence:.2f}")
    print(f"BBox: {face.bbox}")
    print(f"Landmarks: {face.landmarks.shape}")  # (5, 2)

Model Variants

from uniface import RetinaFace
from uniface.constants import RetinaFaceWeights

# Lightweight (mobile/edge)
detector = RetinaFace(model_name=RetinaFaceWeights.MNET_025)

# Balanced (default)
detector = RetinaFace(model_name=RetinaFaceWeights.MNET_V2)

# High accuracy
detector = RetinaFace(model_name=RetinaFaceWeights.RESNET34)
Variant Params Size Easy Medium Hard
MNET_025 0.4M 1.7 MB 88.5% 87.0% 80.6%
MNET_050 1.0M 2.6 MB 89.4% 88.0% 82.4%
MNET_V1 3.5M 3.8 MB 90.6% 89.1% 84.1%
MNET_V2 3.2M 3.5 MB 91.7% 91.0% 86.6%
RESNET18 11.7M 27 MB 92.5% 91.0% 86.6%
RESNET34 24.8M 56 MB 94.2% 93.1% 88.9%

Configuration

detector = RetinaFace(
    model_name=RetinaFaceWeights.MNET_V2,
    confidence_threshold=0.5,  # Min confidence
    nms_threshold=0.4,         # NMS IoU threshold
    input_size=(640, 640),     # Input resolution
    dynamic_size=False,        # Enable dynamic input size
    providers=None,            # Auto-detect, or ['CPUExecutionProvider']
)

SCRFD

State-of-the-art detection with excellent accuracy-speed tradeoff.

Basic Usage

from uniface import SCRFD

detector = SCRFD()
faces = detector.detect(image)

Model Variants

from uniface import SCRFD
from uniface.constants import SCRFDWeights

# Real-time (lightweight)
detector = SCRFD(model_name=SCRFDWeights.SCRFD_500M_KPS)

# High accuracy (default)
detector = SCRFD(model_name=SCRFDWeights.SCRFD_10G_KPS)
Variant Params Size Easy Medium Hard
SCRFD_500M_KPS 0.6M 2.5 MB 90.6% 88.1% 68.5%
SCRFD_10G_KPS 4.2M 17 MB 95.2% 93.9% 83.1%

Configuration

detector = SCRFD(
    model_name=SCRFDWeights.SCRFD_10G_KPS,
    confidence_threshold=0.5,
    nms_threshold=0.4,
    input_size=(640, 640),
    providers=None,  # Auto-detect, or ['CPUExecutionProvider']
)

YOLOv5-Face

YOLO-based detection optimized for faces.

Basic Usage

from uniface import YOLOv5Face

detector = YOLOv5Face()
faces = detector.detect(image)

Model Variants

from uniface import YOLOv5Face
from uniface.constants import YOLOv5FaceWeights

# Lightweight
detector = YOLOv5Face(model_name=YOLOv5FaceWeights.YOLOV5N)

# Balanced (default)
detector = YOLOv5Face(model_name=YOLOv5FaceWeights.YOLOV5S)

# High accuracy
detector = YOLOv5Face(model_name=YOLOv5FaceWeights.YOLOV5M)
Variant Size Easy Medium Hard
YOLOV5N 11 MB 93.6% 91.5% 80.5%
YOLOV5S 28 MB 94.3% 92.6% 83.2%
YOLOV5M 82 MB 95.3% 93.8% 85.3%

Fixed Input Size

YOLOv5-Face uses a fixed input size of 640×640.

Configuration

detector = YOLOv5Face(
    model_name=YOLOv5FaceWeights.YOLOV5S,
    confidence_threshold=0.6,
    nms_threshold=0.5,
    nms_mode='numpy',  # or 'torchvision' for faster NMS
    providers=None,    # Auto-detect, or ['CPUExecutionProvider']
)

YOLOv8-Face

Anchor-free detection with DFL (Distribution Focal Loss) for accurate bbox regression.

Basic Usage

from uniface import YOLOv8Face

detector = YOLOv8Face()
faces = detector.detect(image)

Model Variants

from uniface import YOLOv8Face
from uniface.constants import YOLOv8FaceWeights

# Lightweight
detector = YOLOv8Face(model_name=YOLOv8FaceWeights.YOLOV8_LITE_S)

# Recommended (default)
detector = YOLOv8Face(model_name=YOLOv8FaceWeights.YOLOV8N)
Variant Size Easy Medium Hard
YOLOV8_LITE_S 7.4 MB 93.4% 91.2% 78.6%
YOLOV8N 12 MB 94.6% 92.3% 79.6%

Fixed Input Size

YOLOv8-Face uses a fixed input size of 640×640.

Configuration

detector = YOLOv8Face(
    model_name=YOLOv8FaceWeights.YOLOV8N,
    confidence_threshold=0.5,
    nms_threshold=0.45,
    nms_mode='numpy',  # or 'torchvision' for faster NMS
    providers=None,    # Auto-detect, or ['CPUExecutionProvider']
)

Factory Function

Create detectors dynamically:

from uniface import create_detector

detector = create_detector('retinaface')
# or
detector = create_detector('scrfd')
# or
detector = create_detector('yolov5face')
# or
detector = create_detector('yolov8face')

High-Level API

One-line detection:

from uniface import detect_faces

# Using RetinaFace (default)
faces = detect_faces(image, method='retinaface', confidence_threshold=0.5)

# Using YOLOv8-Face
faces = detect_faces(image, method='yolov8face', confidence_threshold=0.5)

Output Format

All detectors return list[Face]:

for face in faces:
    # Bounding box [x1, y1, x2, y2]
    bbox = face.bbox

    # Detection confidence (0-1)
    confidence = face.confidence

    # 5-point landmarks (5, 2)
    landmarks = face.landmarks
    # [left_eye, right_eye, nose, left_mouth, right_mouth]

Visualization

from uniface.visualization import draw_detections

draw_detections(
    image=image,
    bboxes=[f.bbox for f in faces],
    scores=[f.confidence for f in faces],
    landmarks=[f.landmarks for f in faces],
    vis_threshold=0.6
)

cv2.imwrite("result.jpg", image)

Performance Comparison

Benchmark on your hardware:

python tools/detection.py --source image.jpg --iterations 100

See Also