Skip to content

Detection

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

Face Detection
SCRFD detection with corner-style bounding boxes and 5-point landmarks

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.detection 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.detection 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.detection import SCRFD

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

Model Variants

from uniface.detection 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.detection import YOLOv5Face

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

Model Variants

from uniface.detection 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.detection import YOLOv8Face

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

Model Variants

from uniface.detection 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.detection import create_detector

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

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.draw import draw_detections

draw_detections(
    image=image,
    faces=faces,
    vis_threshold=0.6,
)

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

Performance Comparison

Benchmark on your hardware:

python tools/detect.py --source image.jpg

See Also