A faithful Python port of OFIQ v1.1.0 (ISO/IEC 29794-5 face image quality), matching the reference within ±1.
Project description
ofiqpy — a faithful Python port of OFIQ v1.1.0
A behavior-preserving Python reimplementation of the BSI OFIQ ISO/IEC 29794-5
face image quality library. ofiqpy reuses OFIQ's own model files and reproduces
its exact .cpp algorithms, matching the live OFIQ reference to within ±1 per
component (the ISO/IEC 29794-5 Annex A.2 conformance criterion).
📖 Docs: https://avhbac.github.io/ofiqpy/
Status: full coverage + near-exact parity. All 27 ISO components + UnifiedQualityScore, an OFIQ-compatible CSV writer, a CLI, and a parallel batch runner — all gated against live
OFIQSampleApp. Validated on 1,000+ real CelebA images: 27/28 components fully conformant (±1 on every image, most bit-exact); ~99.99% of all component-image pairs within ±1. The rare per-image residuals are numerical boundaries of discrete/learned models (RTrees vote, AdaBoost score, round tie), not algorithm gaps.
Install & run
pip install ofiqpy
export OFIQPY_OFIQ_DATA=/path/to/OFIQ-Project/data # OFIQ's models (not bundled)
ofiqpy -i face.jpg -o out.csv # CLI
from ofiqpy import assess
scores = assess("face.jpg") # {component: (raw, scalar)}
print(scores["UnifiedQualityScore"]) # (magnitude, 0-100)
See Installation and Quickstart.
Design
- Same weights. Models are loaded directly from the reference checkout
OFIQ-Project/data/models/viaconfig.py(SSD caffemodel, ADNet-98 ONNX, 3DDFA-V2 ONNX, BiSeNet parsing ONNX, occlusion-seg ONNX, ssim-248 ONNX, MagFace ONNX). No re-training, no substitute backbones. - Same math. Detection, ADNet landmark crop/denorm, the 5-point LMEDS similarity
alignment to 616×616, the landmarked-region mask,
tmetric, the generich·(a+s·sigmoid(x;x0,w))scalar mapping, and each measure are ported line-faithfully from OFIQ's C++ (see per-module docstrings forfile:lineprovenance). - Same versions. The isolated
.venvpins OpenCV 4.5.5 and onnxruntime 1.18.1 to match OFIQ's build (libofiq_lib.solinks OpenCV 4.5.5; bundles onnxruntime 1.18.1). - Gated, not asserted.
tests/verify_ofiq.pyruns live OFIQ and checks|port_scalar − ofiq_scalar| ≤ 1per image;tests/gate_slice.pyreports it.
Conformance (1,000+ real CelebA images, port vs live OFIQ, ISO Annex A ±1)
Validated on 1,197 real CelebA images: 27 of 28 components fully conformant (±1 on every image), 24 of them bit-exact (maxΔ=0). ~99.99% of all component-image pairs are within ISO ±1 (mean |Δ| ≤ 0.02 for every component).
The rare per-image residuals:
- Sharpness — 1 image at Δ=2: OFIQ's RTrees vote count differs by exactly 2 trees at a split-threshold knife-edge (a sub-LSB feature difference flips 2 borderline votes through the step-function forest). Bit-exact on the rest.
- BackgroundUniformity / ExpressionNeutrality / NoHeadCoverings — one ±1 image each, a single sigmoid/round boundary.
Sharpness (RTrees) and ExpressionNeutrality (dual EfficientNet + AdaBoost) run OFIQ's own
cv2.ml / ONNX models; UnifiedQualityScore runs OFIQ's MagFace ONNX. These four residuals
are numerical boundaries of discrete/learned models, not algorithm gaps.
How parity was reached (the residual was a bug, not a build limit)
An earlier version of this port was only ~96% conformant, and the residual was wrongly
attributed to a build-level OpenCV float difference. To test that, ctypes bridges were
built against OFIQ's own conan OpenCV static libs (native/ofiq_cv.cpp, ofiq_ssd.cpp)
and used to compare OFIQ's compiled estimateAffinePartial2D, warpAffine, resize, and
the SSD dnn forward pass against the pip opencv-python wheel. Every OpenCV operation
was bit-identical — which disproved the build-level theory and localized the divergence
to the ADNet landmark back-projection: OFIQ scales landmarks back with
squareBox.height / 256 (adnet_landmarks.cpp:313), but makeSquareBoundingBox's
floor/ceil can leave the box 1px non-square, and the port had used the width. On
exactly-square detector boxes it matched; otherwise it drifted ~1px, propagating (via the
alignment source points → affine → whole aligned face) into every landmark-sensitive
measure. One-character fix (width→height); all 27 non-model components went bit-exact.
The bridges in native/ are diagnostic only — the runtime uses pip cv2, which is
bit-identical to OFIQ's OpenCV. No source build of OpenCV was needed.
Layout
ofiqpy/
config.py JAXN loader + OFIQ model resolver + sigmoid params
sigmoid.py OFIQ ScalarConversion (Measure.h:271-285)
session.py shared preprocessing products
pipeline.py detect -> pose -> landmarks -> align -> parse -> occlusion -> region
detectors/ssd.py SSD (OpenCV DNN, Caffe)
landmarks/adnet.py ADNet-98 + square-crop helpers
align.py 616x616 alignment, landmarked region (GetFaceMask), tmetric, luminance
pose/tddfa.py 3DDFA-V2 pose
segmentation/ BiSeNet parsing, face-occlusion seg
measures/
core.py model cache + dispatch; C03/C09/C17/C20, unified, HeadPose (slot swap)
geometry.py C11,C12,C13,C19,C24-C27
pixel.py C01,C02,C04(var),C05,C06,C07,C10
models.py C08 Sharpness (RTrees), C14/C15/C16 occlusion, C18 Expression
helpers.py get_distance/get_middle, c_round, landmark index maps
output.py OFIQ-format CSV (named cols, raw + .scalar)
cli.py OFIQSampleApp-compatible CLI
tests/
verify_ofiq.py runs live OFIQ, ±1 gate
gate_slice.py full-coverage conformance runner
Run
export OFIQPY_OFIQ_DATA=/path/to/OFIQ-Project/data
ofiqpy -i <image|dir> -o out.csv # single / small runs (OFIQ-format CSV)
python -m ofiqpy.batch -i <dir> -o out.csv -w 8 --resume # parallel batch
# reproduce the conformance gate (needs a built OFIQSampleApp)
export OFIQPY_OFIQ_ROOT=/path/to/OFIQ-Project
export OFIQPY_TEST_IMAGES=/path/to/images
python tests/gate_slice.py 1000
Full documentation: https://avhbac.github.io/ofiqpy/.
License & attribution
ofiqpy is released under the MIT License.
It is a faithful port of OFIQ (Open Source Face Image Quality), developed by the German Federal Office for Information Security (BSI), Copyright © 2024, MIT-licensed (https://github.com/BSI-OFIQ/OFIQ-Project). Please acknowledge OFIQ when using ofiqpy.
Models are not bundled. ofiqpy loads OFIQ's own model files at runtime; they ship with
OFIQ and may be licensed separately (see OFIQ's LICENSE.md). Obtain them from an OFIQ
install and set OFIQPY_OFIQ_DATA. See NOTICE and the
licensing docs.
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 ofiqpy-0.1.1.tar.gz.
File metadata
- Download URL: ofiqpy-0.1.1.tar.gz
- Upload date:
- Size: 45.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e6681ded33f6db598e657640e64fc01405d2525b985ef5c119d8a0e5f9a3864
|
|
| MD5 |
1eee6b707267abbd3327bd7aed7b9d97
|
|
| BLAKE2b-256 |
edaa6c7b1e11783a383e6c40ade7276ec19645432d7b26c1ea47aa59f9d83d52
|
Provenance
The following attestation bundles were made for ofiqpy-0.1.1.tar.gz:
Publisher:
workflow.yml on AVHBAC/ofiqpy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ofiqpy-0.1.1.tar.gz -
Subject digest:
9e6681ded33f6db598e657640e64fc01405d2525b985ef5c119d8a0e5f9a3864 - Sigstore transparency entry: 2193196139
- Sigstore integration time:
-
Permalink:
AVHBAC/ofiqpy@c80fb388fe1ccecd17f60f296a1ef31bd95a1ee3 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/AVHBAC
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@c80fb388fe1ccecd17f60f296a1ef31bd95a1ee3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ofiqpy-0.1.1-py3-none-any.whl.
File metadata
- Download URL: ofiqpy-0.1.1-py3-none-any.whl
- Upload date:
- Size: 34.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a728f40d0bd57e7582c4a6a84b5330dc2facc0644a3f0ee315af590d2ca2af4a
|
|
| MD5 |
aa634f9a547514a5fa196802909af4dc
|
|
| BLAKE2b-256 |
bd992a37f9ee3f8fd72dd909d2b0de6847a99cf79dee89f60a3079861faf68f9
|
Provenance
The following attestation bundles were made for ofiqpy-0.1.1-py3-none-any.whl:
Publisher:
workflow.yml on AVHBAC/ofiqpy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ofiqpy-0.1.1-py3-none-any.whl -
Subject digest:
a728f40d0bd57e7582c4a6a84b5330dc2facc0644a3f0ee315af590d2ca2af4a - Sigstore transparency entry: 2193196164
- Sigstore integration time:
-
Permalink:
AVHBAC/ofiqpy@c80fb388fe1ccecd17f60f296a1ef31bd95a1ee3 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/AVHBAC
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@c80fb388fe1ccecd17f60f296a1ef31bd95a1ee3 -
Trigger Event:
push
-
Statement type: