MLX-UniFace: Blazing-fast face analysis on Apple Silicon with MLX backend
Project description
MLX-UniFace: Blazing-Fast Face Analysis on Apple Silicon
MLX-UniFace is a high-performance face analysis library optimized for Apple Silicon. It provides face detection, recognition, landmark detection, and attribute analysis with native MLX acceleration.
This is a fork of yakhyo/uniface with added MLX backend support for Apple Silicon Macs.
Why MLX-UniFace?
| Feature | MLX-UniFace | Original UniFace |
|---|---|---|
| Apple Silicon Native | Yes (MLX) | ONNX via CoreML |
| Unified Memory | Yes | No |
| Backend | MLX + ONNX fallback | ONNX only |
| M1/M2/M3/M4 Optimized | Yes | Partial |
Performance Benefits on Apple Silicon
- Unified Memory: No CPU-GPU data transfer overhead
- Native Acceleration: Optimized for Apple's Neural Engine and GPU
- Lazy Evaluation: Automatic graph optimization
- Numerical Parity: Identical results to ONNX (correlation = 1.0)
Installation
For Apple Silicon (Recommended)
pip install mlx-uniface
With MLX Backend (Explicit)
pip install mlx-uniface[mlx]
With ONNX Fallback
pip install mlx-uniface[onnx]
Install from Source
git clone https://github.com/CodeWithBehnam/mlx-uniface.git
cd mlx-uniface
pip install -e ".[mlx]"
Quick Start
Face Detection
import cv2
from uniface import RetinaFace
# Automatically uses MLX on Apple Silicon
detector = RetinaFace()
image = cv2.imread("image.jpg")
faces = detector.detect(image)
for face in faces:
bbox = face['bbox'] # [x1, y1, x2, y2]
confidence = face['confidence']
landmarks = face['landmarks'] # 5-point landmarks
print(f"Face detected with confidence: {confidence:.2f}")
Face Recognition
from uniface import ArcFace, RetinaFace
from uniface import compute_similarity
detector = RetinaFace()
recognizer = ArcFace()
# Detect and extract embeddings
faces1 = detector.detect(image1)
faces2 = detector.detect(image2)
embedding1 = recognizer.get_normalized_embedding(image1, faces1[0]['landmarks'])
embedding2 = recognizer.get_normalized_embedding(image2, faces2[0]['landmarks'])
# Compare faces
similarity = compute_similarity(embedding1, embedding2)
print(f"Similarity: {similarity:.4f}")
Age & Gender Detection
from uniface import RetinaFace, AgeGender
detector = RetinaFace()
age_gender = AgeGender()
faces = detector.detect(image)
gender, age = age_gender.predict(image, faces[0]['bbox'])
print(f"{'Female' if gender == 0 else 'Male'}, {age} years old")
Supported Models
Detection
| Model | Variants | MLX | ONNX |
|---|---|---|---|
| RetinaFace | MobileNet 0.25/0.5/v1/v2, ResNet18/34 | ✅ | ✅ |
| SCRFD | 500M, 10G | ✅ | ✅ |
| YOLOv5Face | S, M | ✅ | ✅ |
Recognition
| Model | Variants | MLX | ONNX |
|---|---|---|---|
| ArcFace | MobileNet, ResNet | ✅ | ✅ |
| MobileFace | v1, v2, v3 | ✅ | ✅ |
| SphereFace | Sphere20 | ✅ | ✅ |
Attributes
| Model | Output | MLX | ONNX |
|---|---|---|---|
| Landmark106 | 106-point landmarks | ✅ | ✅ |
| AgeGender | Age + Gender | ✅ | ✅ |
| Emotion | 7/8 emotions | ✅ | ✅ |
Backend Selection
MLX-UniFace automatically selects the best backend:
- Apple Silicon + MLX installed → Uses MLX (fastest)
- Otherwise → Uses ONNX Runtime
Force a Specific Backend
import os
os.environ['UNIFACE_BACKEND'] = 'mlx' # Force MLX
os.environ['UNIFACE_BACKEND'] = 'onnx' # Force ONNX
from uniface import RetinaFace
detector = RetinaFace() # Uses the specified backend
Check Current Backend
from uniface.backend import get_backend, Backend
backend = get_backend()
print(f"Using: {backend}") # Backend.MLX or Backend.ONNX
Benchmarks
Run benchmarks on your hardware:
# Quick benchmark
python scripts/test_mlx_detection.py
# Full benchmark with visualization
jupyter notebook notebooks/benchmark_mlx_vs_onnx.ipynb
Numerical Parity Verification
python scripts/verify_numerical_parity.py
Output:
✓ SUCCESS: MLX and ONNX outputs match within tolerance!
All outputs have correlation > 0.999
Development
Setup
git clone https://github.com/CodeWithBehnam/mlx-uniface.git
cd mlx-uniface
pip install -e ".[dev]"
Run Tests
pytest
Code Formatting
ruff format .
ruff check . --fix
Project Structure
mlx-uniface/
├── uniface/
│ ├── detection/ # Face detection (RetinaFace, SCRFD, YOLOv5)
│ │ ├── retinaface.py # ONNX implementation
│ │ ├── retinaface_mlx.py # MLX implementation
│ │ └── ...
│ ├── recognition/ # Face recognition (ArcFace, MobileFace)
│ ├── landmark/ # 106-point landmarks
│ ├── attribute/ # Age, Gender, Emotion
│ ├── nn/ # MLX neural network modules
│ │ ├── backbone.py # MobileNetV1/V2
│ │ ├── conv.py # Conv layers with fused BatchNorm
│ │ ├── fpn.py # Feature Pyramid Network
│ │ └── head.py # Detection heads
│ ├── backend.py # Backend auto-selection
│ ├── mlx_utils.py # MLX utilities
│ └── onnx_utils.py # ONNX utilities
├── scripts/
│ ├── convert_onnx_to_mlx.py # Weight conversion
│ ├── verify_numerical_parity.py # Accuracy validation
│ └── test_mlx_detection.py # End-to-end tests
├── notebooks/
│ └── benchmark_mlx_vs_onnx.ipynb
└── weights_mlx/ # Pre-converted MLX weights
Credits
- Original UniFace: yakhyo/uniface by Yakhyokhuja Valikhujaev
- MLX Framework: Apple MLX
- Model Architectures:
License
MIT License - see LICENSE for details.
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
- Issues: GitHub Issues
- Original Project: yakhyo/uniface
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mlx_uniface-1.0.0.tar.gz.
File metadata
- Download URL: mlx_uniface-1.0.0.tar.gz
- Upload date:
- Size: 79.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75fc5177f9c09c601ffb19267770c9fc526b0733b1da3be5589c3fb2810ef10e
|
|
| MD5 |
e4eb3c0c50177db9f8cab9b1f77e475b
|
|
| BLAKE2b-256 |
b59bddce5a38764a117cc90a38c6846fd3c6682c794a6b50737acdc1869ac6d9
|
Provenance
The following attestation bundles were made for mlx_uniface-1.0.0.tar.gz:
Publisher:
publish.yml on CodeWithBehnam/mlx-uniface
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mlx_uniface-1.0.0.tar.gz -
Subject digest:
75fc5177f9c09c601ffb19267770c9fc526b0733b1da3be5589c3fb2810ef10e - Sigstore transparency entry: 755656720
- Sigstore integration time:
-
Permalink:
CodeWithBehnam/mlx-uniface@16babe07b9ad138271219d01bb66c53e1d2db149 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/CodeWithBehnam
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@16babe07b9ad138271219d01bb66c53e1d2db149 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file mlx_uniface-1.0.0-py3-none-any.whl.
File metadata
- Download URL: mlx_uniface-1.0.0-py3-none-any.whl
- Upload date:
- Size: 102.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42e5773e9b76db6cbe233161315e0572c3aed206cca7cd9138e3c8e5a8ca4e8a
|
|
| MD5 |
d941046ec9a14b66fd8e3b074887d88f
|
|
| BLAKE2b-256 |
bd9c7dbdf2944f3cbdbb7a6e406593bc69270cd5516b41ceddc0334b458be6a5
|
Provenance
The following attestation bundles were made for mlx_uniface-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on CodeWithBehnam/mlx-uniface
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mlx_uniface-1.0.0-py3-none-any.whl -
Subject digest:
42e5773e9b76db6cbe233161315e0572c3aed206cca7cd9138e3c8e5a8ca4e8a - Sigstore transparency entry: 755656763
- Sigstore integration time:
-
Permalink:
CodeWithBehnam/mlx-uniface@16babe07b9ad138271219d01bb66c53e1d2db149 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/CodeWithBehnam
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@16babe07b9ad138271219d01bb66c53e1d2db149 -
Trigger Event:
workflow_dispatch
-
Statement type: