AlchemyFace
Face detection and recognition built on YuNet and SFace. Small, typed, and dependency-light: OpenCV, NumPy, Typer. Nothing else.
Why
Most Python face-recognition libraries pull in dlib, PyTorch or TensorFlow. AlchemyFace uses two small ONNX models through OpenCV's own DNN runtime, so a working install is a few megabytes of Python and about 37 MB of weights fetched once, on first use.
Install
pip install alchemyface
Use
import cv2
from alchemyface import Recognizer
r = Recognizer() # weights download once, then cached
r.enroll("prashant", cv2.imread("me.jpg"))
r.enroll("alice", cv2.imread("alice.jpg"))
for recognition in r.identify(cv2.imread("group.jpg")):
face, match = recognition.face, recognition.match
if match:
print(f"{match.label} at {face.bbox} ({match.score:.2f})")
else:
print(f"unknown face at {face.bbox}")
Enrolled faces live in memory. Persist them when you are done:
r.store.save("gallery.npz")
r.store.load("gallery.npz")
Bring your own components
Recognizer is a thin facade over three protocols — Detector, Embedder and
FaceStore. Any object satisfying the protocol can be substituted, which is how
a pgvector-backed store or a different embedding model will slot in later
without touching the pipeline.
from alchemyface import Recognizer
from alchemyface.detection import YuNetDetector
from alchemyface.embedding import SFaceEmbedder
from alchemyface.store import InMemoryStore
r = Recognizer(
detector=YuNetDetector(score_threshold=0.8),
embedder=SFaceEmbedder(),
store=InMemoryStore(),
threshold=0.363,
)
Live video
from alchemyface import Recognizer
from alchemyface.capture import VideoSource
r = Recognizer()
r.store.load("gallery.npz")
with VideoSource(0, width=1280, height=720) as camera:
for frame in camera.frames():
for recognition in r.identify(frame):
match = recognition.match
print(match.label if match else "unknown", recognition.face.bbox)
CLI
alchemyface download-models # pre-fetch weights
alchemyface enroll --name prashant --image me.jpg --gallery g.npz
alchemyface identify --image group.jpg --gallery g.npz
Model weights
Weights are resolved in this order, first hit wins:
model_dir=passed toRecognizer$ALCHEMYFACE_MODEL_DIR~/.cache/alchemyface/models/- downloaded from the OpenCV Zoo and SHA256-verified
To work fully offline, point at a directory you already have:
export ALCHEMYFACE_MODEL_DIR=/path/to/onnx
The recognition threshold
The default cosine threshold is 0.363, SFace's published operating point:
above it, two embeddings are treated as the same person. Raise it for fewer
false accepts, lower it for fewer false rejects. It is a tunable, not a
constant — validate it against your own data before relying on it.
Development
Requires pyenv with
pyenv-virtualenv.
pyenv install 3.10.6 # if not already present
pyenv virtualenv 3.10.6 alchemyface # .python-version activates it here
pip install -e ".[dev]"
| Command | Does |
|---|---|
pytest tests/ -m "not models and not camera" |
the fast suite — no models, camera or network |
pytest tests/ -m "not camera" |
adds the tests that load the real ONNX weights |
ruff check src tests |
lint |
ruff format src tests |
format |
mypy src/alchemyface |
type check |
python -m build |
build the wheel and sdist |
Tests that need the real weights are marked models and skip unless
ALCHEMYFACE_MODEL_DIR points at a directory containing them:
export ALCHEMYFACE_MODEL_DIR="$PWD/_local/onnx"
A note on data
This repository contains a _local/ directory that is git-ignored and must
stay that way. It holds face embeddings, name recordings and captured images
of real, identifiable people, carried over from the internal prototype this
library grew out of. Under Japan's APPI and GDPR Article 9 those are sensitive
personal data. They are development fixtures only: they are excluded from the
wheel, the sdist and version control, and they must never be published.
Licence
MIT — see LICENSE.
The ONNX weights are distributed by the OpenCV Zoo under their own terms — YuNet under MIT, SFace under Apache-2.0 — and are downloaded at runtime rather than redistributed here.
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 alchemyface-0.3.0.tar.gz.
File metadata
- Download URL: alchemyface-0.3.0.tar.gz
- Upload date:
- Size: 30.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
422ecc6aa7317e4693f11d13a17bee4682576f70370b7f19e266185ed99881af
|
|
| MD5 |
9d9c7f3c09daae9d7add42beacd07f4e
|
|
| BLAKE2b-256 |
57eebb1b2450fdc7c682e0507a17ae450b07833c5c334f1a9dcd86d777bf7b34
|
File details
Details for the file alchemyface-0.3.0-py3-none-any.whl.
File metadata
- Download URL: alchemyface-0.3.0-py3-none-any.whl
- Upload date:
- Size: 32.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d26a14187a7c5e89f6e9417688ec99d1eb7fd9564382c4ba403ad30ccc8fdb57
|
|
| MD5 |
3a794372f3610caadcb9ad077f326194
|
|
| BLAKE2b-256 |
2a3233a4ff0a07494523edb74700835a160013a21515d0515c33152d3bd42fe8
|