Files
uniface/docs/quickstart.md
Yakhyokhuja Valikhujaev 4d6f29a113 feat: Release v4.0.0 (#130)
* docs: Minor info changes

* refactor: Remove deprecated factory functions

Removes the 10 factory functions deprecated in v3.7.0:
create_detector, list_available_detectors, create_recognizer,
create_face_parser, create_gaze_estimator, create_head_pose_estimator,
create_landmarker, create_matting_model, create_spoofer,
create_attribute_predictor.

Instantiate model classes directly instead, e.g.
`from uniface.detection import SCRFD; SCRFD()`.

Also drops the now-unused typing_extensions dependency and updates
docstring examples that referenced the factories.

* refactor: Remove MODEL_URLS and MODEL_SHA256 back-compat mirrors

Use MODEL_REGISTRY instead of the MODEL_URLS and MODEL_SHA256 dicts in
uniface.constants.

* chore: Add .claude directory to gitignore

* ci: Deploy docs via GitHub Pages artifact instead of gh-pages branch

* feat: Add FaceAttribNet face state prediction model

Integrate Qualcomm's FaceAttribNet (Facial-Attribute-Detection) as a new
attribute model predicting five independent binary face states from a
face crop: left/right eye openness, eyeglasses, mask, and sunglasses.

- Add FaceAttribNet class with letterbox preprocessing (normalization is
  baked into the ONNX graph) and multi-label FaceStateResult output
- Register FaceAttribNetWeights with dynamic-batch ONNX weights (opset 17)
- Enrich Face with left_eye_open, right_eye_open, eyeglasses, mask,
  and sunglasses fields
- Rename AttributeResult to DemographyResult and DDAMFNWeights to
  EmotionWeights so 'attribute' unambiguously means the model category
- Add tests and docs

* docs: Add face attributes notebook, demo assets, and README updates

* feat: Add CenterFace face detection model

* docs: Add CONTEXT.md glossary and ADRs for v4 naming decisions

ADR-0001: Face.landmarks keeps its v3 name for the 5-point set; the
future dense-landmark slot will be Face.dense_landmarks.
ADR-0002: Attribute stays the per-face predictor base class name;
FaceAnalyzer(attributes=...) is unchanged.

* refactor: Rename FaceAnalyzer attributes parameter to predictors

The pipeline parameter names the role (per-face predictors), so future
head pose, gaze, spoofing, and quality models can be passed without the
semantic mismatch of being listed as attributes. The Attribute base
class keeps its name per ADR-0002.

BREAKING CHANGE: FaceAnalyzer(attributes=...) is now
FaceAnalyzer(predictors=...); FaceAnalyzer.attributes is now
FaceAnalyzer.predictors.

* docs: Update docs and notebooks for predictors parameter rename

* docs: Remove CONTEXT.md

* docs: Restore README badges

* docs: Remove ADR folder

* refactor: Rename Attribute base class to BaseAttribute

* docs: Replace thick README separators with heading underlines

* docs: Put README tagline in a callout

* fix: Use predictors= in the analyze tool

* refactor: Make supports_landmarks a class attribute on BaseDetector

Replaces the private _supports_landmarks instance flag and its read-only
property with a plain class attribute, mirroring supports_alignment. Every
detector set the flag to True in __init__, so the False default never
survived and the hasattr guard in the property was dead weight.

Also drops a stale Attributes entry in RetinaFace for a field that no
longer exists, and removes comments that restated the call beneath them.

* docs: Normalize docstring markup and document missing raises

Audited every docstring and comment in uniface/ against the detection
package, which is the most internally consistent one.

- Replace 13 Sphinx roles and 159 RST double-backticks with markdown
  backticks; nothing renders docstrings, there is no Sphinx, and mkdocs
  has no mkdocstrings plugin
- Rewrite 59 legacy typing generics (List, Tuple, Optional, Union) to
  PEP 585, each checked against the real signature rather than
  mechanically substituted
- Add Raises sections to download_file, compute_similarity and
  parse_with_inverse, which raised undocumented exceptions
- Drop the RuntimeError Raises block from six abstract _initialize_model
  methods whose body raises NotImplementedError; the contract belongs to
  the implementer and is now stated as prose
- Fold Properties into Attributes with a Read-only prefix, singularize
  Examples, and fix the copyright year in faceattribnet

No executable line changed; the bulk pass rewrote only string and comment
tokens matched by byte offset.

* fix: Raise ValueError instead of asserting in estimate_norm

Both input checks used bare assert statements, which python -O strips.
The docstring promised AssertionError as part of the contract, so under an
optimized build the validation silently disappeared and an unsupported
image_size flowed into the alignment maths instead of failing fast.

Both are now ValueError, and the messages report the offending value.

* docs: Replace RST double-backticks in face_utils

* docs: Document Raises on every model class

The detection package documents ValueError and RuntimeError on the class
docstring; no model class in any other package did, even though they all
call verify_model_weights in __init__ and reach an _initialize_model that
wraps session creation in RuntimeError.

Verified per class before adding: each target reaches both raise sites,
inheriting _initialize_model from its base where it does not define one.

* fix: Replace the last two bare asserts with explicit raises

python -O strips assert statements, so both checks silently disappeared in
optimized builds. BaseRecognizer would then accept a multi-output model and
mis-slice its results, and get_meanface_info would build neighbour tables
from a meanface of the wrong length.

Behaviour is unchanged in normal builds: the recognizer check already sat
inside the try that re-raises as RuntimeError, and the meanface check now
raises the ValueError its docstring already documented.

No bare asserts remain in uniface/.

* style: Put multi-line docstring summaries on the first line

Card 6 of the docstring audit: class docstrings opened two different ways,
45 with a leading newline and 37 on the same line as the quotes.

Settled by the repo's own config rather than by taste. pyproject already
declares pydocstyle convention = google, under which ruff resolves D212
(multi-line-summary-first-line) as the active rule and explicitly ignores
the incompatible D213. Same-line was therefore already the declared
standard, even though the detection package -- the audit's exemplar -- sat
on the other side of the split.

Applied with ruff --fix, then the summaries that ended up glued to their
description got the blank line D205 wants.

* style: Put multi-line docstring summaries on the first line (constants, test_utils)

Same D212/D205 pass as the previous commit, applied to the two files that
were held back from it.

* build: Enforce D205 and D212 in ruff

The docstring audit found the opening style split 45/37 with nothing to
hold it in place: pyproject declared pydocstyle convention = google, but D
was absent from select, so the convention setting was inert.

Selecting the two rules the codebase now satisfies makes the decision
checkable instead of conventional. The rest of D is left off deliberately
-- D100 alone would flag 63 files, since this project's convention is to
have no module docstrings.

* feat: Add BlazeFace detector and MediaPipe Face Mesh landmarker

BlazeFace is MediaPipe's short-range SSD face detector: two anchor grids
over a 128x128 letterboxed image, decoded with MediaPipe's weighted NMS
where overlapping candidates are score-averaged rather than discarded.

It emits 6 MediaPipe keypoints, not the 5-point alignment template, so
BaseDetector gains a supports_alignment flag. It is True everywhere else
and False only here. FaceAnalyzer checks it and disables recognition with
a warning instead of producing broken embeddings, and estimate_norm's
error now names the constraint when a caller tries to align anyway.

FaceMesh predicts 468 dense 3D landmarks from a face crop and is
detector-agnostic: the ROI follows MediaPipe's recipe, a square region at
1.5x the detector box rotated so the eye line is horizontal, built from
whichever two eye points the detector provides. Every face in an image
runs in one session call. roi_from_box and warp_roi are public so
video-mode tracking can be built on top.

Also adds FaceMeshResult, draw_mesh with full and partial tessellations,
weight entries for both models, the facemesh and facestate tools, example
notebook 15, and tests for both models.

Tessellation tables are vendored from PINTO0309/facemesh_onnx_tensorrt
(Apache-2.0); provenance is recorded in docs/license-attribution.md.

* docs: List BlazeFace and Face Mesh in the remaining model indexes

The feature commit updated the detection and landmarks module pages, the
model zoo and the concept pages, but four summary listings still predated
both models:

- README examples table stopped at notebook 14
- README training-dataset table omitted both
- quickstart model summary omitted both
- index.md feature cards described detection as 5-point only, which
  BlazeFace's 6 keypoints contradict

* feat: Add MediaPipe Face Landmarker, a 478-point mesh with irises

Google's Face Landmarker is the successor to Face Mesh: one network predicting
478 landmarks from a 256x256 crop, where the first 468 keep the Face Mesh
topology and ordering and the last ten are the irises. It ships in the Tasks
API bundle; the earlier 478-point attention model is not ported, since it needs
three MediaPipe-only TFLite custom ops that no standard runtime can load.

FaceMesh needs no logic change to serve it. Input size and landmark count were
already read from the ONNX graph, so 192->256 and 468->478 are absorbed at load
time. Verified end to end at 0.007% of inter-ocular distance against MediaPipe's
own pipeline, with the existing ROI recipe unchanged - Google's model card
specifies the same 25% per-side margin the default already used.

Iris membership follows MediaPipe's own convention: the result stays a flat
array and the region lives in named constants next to the topology it indexes,
rather than becoming accessors on FaceMeshResult. draw_mesh renders the irises
distinctly, so the library and tools/facemesh.py agree by construction.

BREAKING CHANGE: FaceMeshWeights.DEFAULT is replaced by V1_468 and V2_478.
Default behaviour is unchanged - the constructor still loads the 468-point
model - but code naming DEFAULT explicitly must be updated. Every other
multi-variant weights enum already names its members descriptively.

* feat: Add Hugging Face mirror fallback for weight downloads

* docs: Document the Hugging Face mirror fallback

* fix: Resolve bugs found in whole-codebase review

* refactor: Publish validate_image and normalize line endings

* fix: Guarantee weighted NMS terminates

* refactor: Make model constructors keyword-only

* refactor: Read input_size from the ONNX model

* fix: Normalize and validate attribute input_size

* refactor: Replace detector **kwargs with explicit options

* fix: Reject unusable images in BlazeFace and FaceMesh

* feat: Make detector capability flags opt-in

* fix: Show every populated face state in Face repr

* docs: Clarify inline comments

* docs: Update docs and notebooks for v4

* refactor: Make remaining public constructors keyword-only

* feat: Export BaseAttribute and document custom predictors

* test: Cover FaceAnalyzer predictors

* fix: Pin the Hugging Face mirror to an immutable revision

* docs: Add changelog with v4 migration guide

* ci: Deploy release docs via the Pages artifact flow

* build: Require setuptools 77 for the SPDX license field

* docs: Fix anchors, dataset table, and tool options

* chore: Release v4.0.0rc1

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-04 02:47:26 +09:00

14 KiB

Quickstart

Get up and running with UniFace in 5 minutes. This guide covers the most common use cases.


Face Detection

Detect faces in an image:

import cv2
from uniface.detection import RetinaFace

# Load image
image = cv2.imread("photo.jpg")

# Initialize detector (models auto-download on first use)
detector = RetinaFace()

# Detect faces
faces = detector.detect(image)

# Print results
for i, face in enumerate(faces):
    print(f"Face {i+1}:")
    print(f"  Confidence: {face.confidence:.2f}")
    print(f"  BBox: {face.bbox}")
    print(f"  Landmarks: {len(face.landmarks)} points")

Output:

Face 1:
  Confidence: 0.99
  BBox: [120.5, 85.3, 245.8, 210.6]
  Landmarks: 5 points

Visualize Detections

Draw bounding boxes and landmarks:

import cv2
from uniface.detection import RetinaFace
from uniface.draw import draw_detections

# Detect faces
detector = RetinaFace()
image = cv2.imread("photo.jpg")
faces = detector.detect(image)

# Draw on image
draw_detections(image=image, faces=faces, vis_threshold=0.6)

# Save result
cv2.imwrite("output.jpg", image)

Face Recognition

Compare two faces:

import cv2
from uniface.detection import RetinaFace
from uniface.recognition import ArcFace

# Initialize models
detector = RetinaFace()
recognizer = ArcFace()

# Load two images
image1 = cv2.imread("person1.jpg")
image2 = cv2.imread("person2.jpg")

# Detect faces
faces1 = detector.detect(image1)
faces2 = detector.detect(image2)

if faces1 and faces2:
    # Extract embeddings (normalized 1-D vectors)
    emb1 = recognizer.get_normalized_embedding(image1, faces1[0].landmarks)
    emb2 = recognizer.get_normalized_embedding(image2, faces2[0].landmarks)

    # Compute cosine similarity
    from uniface import compute_similarity
    similarity = compute_similarity(emb1, emb2, normalized=True)

    # Interpret result
    if similarity > 0.6:
        print(f"Same person (similarity: {similarity:.3f})")
    else:
        print(f"Different people (similarity: {similarity:.3f})")

!!! tip "Similarity Thresholds" - > 0.6: Same person (high confidence) - 0.4 - 0.6: Uncertain (manual review) - < 0.4: Different people


Age & Gender Detection

import cv2
from uniface.attribute import AgeGender
from uniface.detection import RetinaFace

# Initialize models
detector = RetinaFace()
age_gender = AgeGender()

# Load image
image = cv2.imread("photo.jpg")
faces = detector.detect(image)

# Predict attributes
for i, face in enumerate(faces):
    result = age_gender.predict(image, face)
    print(f"Face {i+1}: {result.sex}, {result.age} years old")

Output:

Face 1: Male, 32 years old
Face 2: Female, 28 years old

FairFace Attributes

Detect race, gender, and age group:

import cv2
from uniface.attribute import FairFace
from uniface.detection import RetinaFace

detector = RetinaFace()
fairface = FairFace()

image = cv2.imread("photo.jpg")
faces = detector.detect(image)

for i, face in enumerate(faces):
    result = fairface.predict(image, face)
    print(f"Face {i+1}: {result.sex}, {result.age_group}, {result.race}")

Output:

Face 1: Male, 30-39, East Asian
Face 2: Female, 20-29, White

Facial Landmarks (106 / 98 / 68 / 468 / 478 Points)

UniFace ships three dense-landmark families. Pick whichever fits your downstream task:

import cv2
from uniface.detection import RetinaFace
from uniface.landmark import Landmark106

detector = RetinaFace()
landmarker = Landmark106()  # 106-point InsightFace 2d106det model

image = cv2.imread("photo.jpg")
faces = detector.detect(image)

if faces:
    landmarks = landmarker.get_landmarks(image, faces[0].bbox)
    print(f"Detected {len(landmarks)} landmarks")  # 106

    # Draw landmarks
    for x, y in landmarks.astype(int):
        cv2.circle(image, (x, y), 2, (0, 255, 0), -1)

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

PIPNet (98 / 68 points) — ResNet-18 backbone trained on WFLW (98 pts) or 300W+CelebA (68 pts):

from uniface.constants import PIPNetWeights
from uniface.landmark import PIPNet

# 98-point WFLW model (default)
landmarker_98 = PIPNet()

# 68-point 300W+CelebA model
landmarker_68 = PIPNet(model_name=PIPNetWeights.DW300_CELEBA_68)

landmarks = landmarker_98.get_landmarks(image, faces[0].bbox)  # (98, 2)

Face Mesh (468 / 478 points, 3D) is MediaPipe's dense mesh, run over every detected face in a single batched call. Pass FaceMeshWeights.V2_478 for the 478-point variant with irises:

from uniface.landmark import FaceMesh

mesher = FaceMesh()  # default: 468 points
results = mesher.predict(image, faces)

print(results[0].landmarks.shape)  # (468, 3), x/y in image pixels, z is relative depth
print(results[0].points_2d.shape)  # (468, 2), depth dropped
print(results[0].score)            # face presence, [0, 1]

Gaze Estimation

import cv2
import numpy as np
from uniface.detection import RetinaFace
from uniface.gaze import MobileGaze
from uniface.draw import draw_gaze

detector = RetinaFace()
gaze_estimator = MobileGaze()

image = cv2.imread("photo.jpg")
faces = detector.detect(image)

for i, face in enumerate(faces):
    x1, y1, x2, y2 = map(int, face.bbox[:4])
    face_crop = image[y1:y2, x1:x2]

    if face_crop.size > 0:
        result = gaze_estimator.estimate(face_crop)
        print(f"Face {i+1}: pitch={np.degrees(result.pitch):.1f}°, yaw={np.degrees(result.yaw):.1f}°")

        # Draw gaze direction
        draw_gaze(image, face.bbox, result.pitch, result.yaw)

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

Head Pose Estimation

import cv2
from uniface.detection import RetinaFace
from uniface.headpose import HeadPose
from uniface.draw import draw_head_pose

detector = RetinaFace()
head_pose = HeadPose()

image = cv2.imread("photo.jpg")
faces = detector.detect(image)

for i, face in enumerate(faces):
    x1, y1, x2, y2 = map(int, face.bbox[:4])
    face_crop = image[y1:y2, x1:x2]

    if face_crop.size > 0:
        result = head_pose.estimate(face_crop)
        print(f"Face {i+1}: pitch={result.pitch:.1f}°, yaw={result.yaw:.1f}°, roll={result.roll:.1f}°")

        # Draw 3D cube visualization
        draw_head_pose(image, face.bbox, result.pitch, result.yaw, result.roll)

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

Face Parsing

Segment face into semantic components:

import cv2
import numpy as np
from uniface.parsing import BiSeNet
from uniface.draw import vis_parsing_maps

parser = BiSeNet()

# Load face image (already cropped)
face_image = cv2.imread("face.jpg")

# Parse face into 19 components
mask = parser.parse(face_image)

# Visualize with overlay (BGR in, BGR out — same convention as cv2)
vis_result = vis_parsing_maps(face_image, mask, save_image=False)

print(f"Detected {len(np.unique(mask))} facial components")

Portrait Matting

Remove backgrounds without a trimap:

import cv2
import numpy as np
from uniface.matting import MODNet

matting = MODNet()

image = cv2.imread("portrait.jpg")
matte = matting.predict(image)  # (H, W) float32 in [0, 1]

# Transparent PNG
rgba = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)
rgba[:, :, 3] = (matte * 255).astype(np.uint8)
cv2.imwrite("transparent.png", rgba)

# Green screen
matte_3ch = matte[:, :, np.newaxis]
bg = np.full_like(image, (0, 177, 64), dtype=np.uint8)
result = (image * matte_3ch + bg * (1 - matte_3ch)).astype(np.uint8)
cv2.imwrite("green_screen.jpg", result)

Face Anonymization

Blur faces for privacy protection:

import cv2
from uniface.detection import RetinaFace
from uniface.privacy import BlurFace

detector = RetinaFace()
blurrer = BlurFace(method='pixelate')

image = cv2.imread("group_photo.jpg")
faces = detector.detect(image)
anonymized = blurrer.anonymize(image, faces)
cv2.imwrite("anonymized.jpg", anonymized)

Custom blur settings:

blurrer = BlurFace(method='gaussian', blur_strength=5.0)
anonymized = blurrer.anonymize(image, faces)

Available methods:

Method Description
pixelate Blocky effect (news media standard)
gaussian Smooth, natural blur
blackout Solid color boxes (maximum privacy)
elliptical Soft oval blur (natural face shape)
median Edge-preserving blur

Face Anti-Spoofing

Detect real vs. fake faces:

import cv2
from uniface.detection import RetinaFace
from uniface.spoofing import MiniFASNet

detector = RetinaFace()
spoofer = MiniFASNet()

image = cv2.imread("photo.jpg")
faces = detector.detect(image)

for i, face in enumerate(faces):
    result = spoofer.predict(image, face.bbox)
    label = 'Real' if result.is_real else 'Fake'
    print(f"Face {i+1}: {label} ({result.confidence:.1%})")

Face Image Quality Assessment

Score how usable each face is for downstream recognition:

import cv2
from uniface.detection import SCRFD
from uniface.quality import EDifFIQA

detector = SCRFD(confidence_threshold=0.3)
quality = EDifFIQA()

image = cv2.imread("photo.jpg")
faces = detector.detect(image)

for i, face in enumerate(faces):
    result = quality.predict(image, face.landmarks)
    print(f"Face {i+1}: quality={result.score:.4f}")

Higher = better. Use it to filter or rank faces before recognition.


Webcam Demo

Real-time face detection:

import cv2
from uniface.detection import RetinaFace
from uniface.draw import draw_detections

detector = RetinaFace()
cap = cv2.VideoCapture(0)

print("Press 'q' to quit")

while True:
    ret, frame = cap.read()
    if not ret:
        break

    faces = detector.detect(frame)

    draw_detections(image=frame, faces=faces)

    cv2.imshow("UniFace - Press 'q' to quit", frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

Face Tracking

Track faces across video frames with persistent IDs:

import cv2
import numpy as np
from uniface.common import xyxy_to_cxcywh
from uniface.detection import SCRFD
from uniface.tracking import BYTETracker
from uniface.draw import draw_tracks

detector = SCRFD()
tracker = BYTETracker(track_thresh=0.5, track_buffer=30)

cap = cv2.VideoCapture("video.mp4")

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break

    faces = detector.detect(frame)
    dets = np.array([[*f.bbox, f.confidence] for f in faces])
    dets = dets if len(dets) > 0 else np.empty((0, 5))

    tracks = tracker.update(dets)

    # Assign track IDs to faces
    if len(tracks) > 0 and len(faces) > 0:
        face_bboxes = np.array([f.bbox for f in faces], dtype=np.float32)
        track_ids = tracks[:, 4].astype(int)

        face_centers = xyxy_to_cxcywh(face_bboxes)[:, :2]
        track_centers = xyxy_to_cxcywh(tracks[:, :4])[:, :2]

        for ti in range(len(tracks)):
            dists = (track_centers[ti, 0] - face_centers[:, 0]) ** 2 + (track_centers[ti, 1] - face_centers[:, 1]) ** 2
            faces[int(np.argmin(dists))].track_id = track_ids[ti]

    tracked_faces = [f for f in faces if f.track_id is not None]
    draw_tracks(image=frame, faces=tracked_faces)
    cv2.imshow("Tracking", frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

For more details, see the Tracking module.


Model Selection

For detailed model comparisons and benchmarks, see the Model Zoo.

Available models by task:

Task Available Models
Detection RetinaFace, SCRFD, CenterFace, YOLOv5Face, YOLOv8Face, BlazeFace (short-range, 6 keypoints)
Recognition ArcFace, AdaFace, EdgeFace, MobileFace, SphereFace
Landmarks Landmark106 (106 pts), PIPNet (98 / 68 pts), FaceMesh (468 or 478 pts, 3D)
Tracking BYTETracker
Gaze MobileGaze (ResNet18/34/50, MobileNetV2, MobileOneS0)
Head Pose HeadPose (ResNet18/34/50, MobileNetV2/V3)
Parsing BiSeNet (ResNet18/34), XSeg
Matting MODNet
Attributes AgeGender, FairFace, Emotion, FaceAttribNet (face states)
Anti-Spoofing MiniFASNet (V1SE, V2)
Quality EDifFIQA (T, S, M, L)
Privacy BlurFace (5 blur methods)
Vector Store FAISS

Verbose Logging

Enable logging to see what happens during model loading and inference (useful for debugging):

import logging
from uniface import enable_logging

enable_logging()                     # INFO level
enable_logging(level=logging.DEBUG)  # DEBUG level

Common Issues

Models Not Downloading

from uniface.model_store import verify_model_weights
from uniface.constants import RetinaFaceWeights

# Manually download a model
model_path = verify_model_weights(RetinaFaceWeights.MNET_V2)
print(f"Model downloaded to: {model_path}")

Check Hardware Acceleration

import onnxruntime as ort
print("Available providers:", ort.get_available_providers())

# macOS M-series should show: ['CoreMLExecutionProvider', ...]
# NVIDIA GPU should show: ['CUDAExecutionProvider', ...]

Slow Performance on Mac

Verify you're using the ARM64 build of Python:

python -c "import platform; print(platform.machine())"
# Should show: arm64 (not x86_64)

Import Errors

from uniface.detection import BlazeFace, CenterFace, RetinaFace, SCRFD, YOLOv5Face, YOLOv8Face
from uniface.recognition import ArcFace, AdaFace
from uniface.attribute import AgeGender, Emotion, FaceAttribNet, FairFace
from uniface.landmark import FaceMesh, Landmark106, PIPNet
from uniface.gaze import MobileGaze
from uniface.headpose import HeadPose
from uniface.matting import MODNet
from uniface.parsing import BiSeNet, XSeg
from uniface.privacy import BlurFace
from uniface.quality import EDifFIQA
from uniface.spoofing import MiniFASNet
from uniface.tracking import BYTETracker
from uniface.analyzer import FaceAnalyzer
from uniface.stores import FAISS  # pip install faiss-cpu
from uniface.draw import draw_detections, draw_tracks

Next Steps

  • Model Zoo - All models, benchmarks, and selection guide
  • API Reference - Explore individual modules and their APIs
  • Tutorials - Step-by-step examples for common workflows
  • Guides - Learn about the architecture and design principles