Skip to main content

ofiqpy

ofiqpy is a Python reimplementation of the fixed, canonical BSI OFIQ v1.1.0 quality-assessment profile. It computes the 27 ISO/IEC 29794-5 components exposed by OFIQ v1.1.0 plus UnifiedQualityScore using OFIQ's model files.

ofiqpy supports one exact contract:

  • OFIQ source tag v1.1.0, commit bb5dc91d00477e02ce53d2530d28e35021484393.
  • The canonical ofiq_config.jaxn with SHA-256 e117286706d799a1e23130db01cfdff7ef36d157b22ecf68dd196052a8a8d0b3.
  • Twelve exact model artifacts totaling 453,497,937 bytes. OFIQConfig hashes every required artifact before creating inference sessions.
  • All 28 canonical output components. Arbitrary JAXN measure lists, scalar overrides, and the full C++ API are not implemented.

Confirmed parity evidence

The strict gate runs the live C++ OFIQSampleApp and this package on all 28 real BSI conformance images. It rejects missing images, duplicate identities, missing components, non-numeric values, and status mismatches.

At the 0.2.0 source state on 2026-08-16:

Observation Result
Official C++ conformance suite 787 / 787 passed
Image/component observations 784 / 784 present
Scalar values exactly equal 784 / 784
Scalar values within tolerance 0 784 / 784
Success/FailureToAssess status equal 784 / 784
Raw values equal at six-decimal CSV precision 698 to 702 / 784 across verified Linux runs
Raw values within the named component policy 784 / 784

Raw values determine the verdict under the immutable bsi-ofiq-v1.1.0-cpu-raw-csv-v1 component policy. The policy compares the six-decimal values emitted by OFIQSampleApp; ten deterministic components require equality and each remaining component has a unit-specific bound and rationale. Raw values are excluded only when either implementation reports FailureToAssess, where OFIQ does not define a raw result. The diagnostic exact count was 698 on the GitHub Python 3.11.15 runner and 702 on the local Python 3.11.14 verification host. This environment-sensitive count is reported, but it does not determine conformance. The earlier unbound 1,197-image and universal bit-exactness claims are not used as release evidence.

A separate, non-redistributed diagnostic reran the recovered 1,197-image CelebA selection with aggregate provenance. All 33,516 statuses matched; 33,483 scalars were exact and all were within one point; all 33,430 defined raw comparisons met the component policy. This binds the currently available bytes but does not retroactively prove that the original unhashed run used identical bytes. See Conformance.

Install and configure

python -m pip install ofiqpy

git clone --branch v1.1.0 https://github.com/BSI-OFIQ/OFIQ-Project.git ../OFIQ-Project
(
  cd ../OFIQ-Project/scripts
  sh build.sh
)

export OFIQPY_OFIQ_ROOT="$(cd ../OFIQ-Project && pwd)"
export OFIQPY_OFIQ_DATA="$OFIQPY_OFIQ_ROOT/data"

The OFIQ build downloads the separately licensed models and BSI test images. ofiqpy does not bundle or redistribute those files. Initialization stops with an integrity error if the downloaded configuration or any required model differs from the verified profile.

Python API

Use Assessor when status and failure information matters:

import os
from pathlib import Path

from ofiqpy import Assessor
from ofiqpy.config import OFIQConfig

data_root = Path(os.environ["OFIQPY_OFIQ_DATA"])
assessor = Assessor(OFIQConfig(data_root=data_root))
result = assessor.assess(data_root / "tests" / "images" / "r-01-frontal.png")

print(result.status)
print(result.components["UnifiedQualityScore"])

Assessor loads and validates the complete model graph before assessment and serializes access to mutable OpenCV/ONNX sessions. A component exception produces a typed FailureToAssess only for that component or compound component group; unaffected results are retained.

The original mapping API remains as a compatibility adapter:

import os
from pathlib import Path

from ofiqpy import assess

image = Path(os.environ["OFIQPY_OFIQ_DATA"]) / "tests" / "images" / "r-01-frontal.png"
scores = assess(image)
print(scores["UnifiedQualityScore"])

It returns {component: (raw, scalar)} and returns an empty mapping only when no face is detected. Unreadable paths, invalid arrays, and preprocessing failures raise instead of being collapsed into a no-face result. New integrations should use Assessor.assess or assess_typed when the typed failure detail is required.

CLI and batch

ofiqpy \
  -i "$OFIQPY_OFIQ_DATA/tests/images/r-01-frontal.png" \
  -o assessment.csv

python -m ofiqpy.batch \
  -i "$OFIQPY_OFIQ_DATA/tests/images" \
  -o assessments.csv \
  --resume

The semicolon CSV uses the canonical 28-component OFIQ column order and preserves the full supplied/discovered image path. CSV quoting protects delimiters in paths. Resume validates the exact header and row width and uses the full path identity, so recursive duplicate basenames do not collide. Batch execution defaults to one worker because each worker owns a complete model graph; additional workers require an explicit -w value and start with Python's clean spawn process context. An unreadable image or preprocessing failure exits nonzero rather than silently writing a whole-image sentinel row.

On the tested 64-image real-data workload, version 0.2.0 processed 2.649 images/s at one worker, 2.391 at two, and 2.140 at four; median process-tree RSS rose from 1.292 GiB to 2.450 and 4.723 GiB. One worker is therefore the measured default for that host, not a universal optimum. See Runtime performance.

Reproduce the strict gate

python -m ofiqpy.conformance \
  --ofiq-root "$OFIQPY_OFIQ_ROOT" \
  --images "$OFIQPY_OFIQ_DATA/tests/images" \
  --expected-count 28 \
  --scalar-tolerance 0 \
  --source-root "$PWD" \
  --report conformance-report.json

The command exits nonzero for any conformance failure or incomplete comparison. The JSON report binds the source tree, OFIQ and ofiqpy commits, official binary and library hashes, canonical config/model hashes, and the complete input set.

License and attribution

ofiqpy is MIT-licensed. OFIQ is developed by the German Federal Office for Information Security (BSI) and is also MIT-licensed. OFIQ's models have their own license terms; review the license files downloaded into the OFIQ data directory before redistribution.

This project is independent and is not endorsed by ISO, IEC, or BSI.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ofiqpy-0.2.0.tar.gz (232.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ofiqpy-0.2.0-py3-none-any.whl (50.3 kB view details)

Uploaded Python 3

File details

Details for the file ofiqpy-0.2.0.tar.gz.

File metadata

  • Download URL: ofiqpy-0.2.0.tar.gz
  • Upload date:
  • Size: 232.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ofiqpy-0.2.0.tar.gz
Algorithm Hash digest
SHA256 2371e1aa4c4cd2ba298b90cbb1364d6d4200e955fffcde2427a51bc8f2c34f4c
MD5 1b94cf1be637269ac7d3c5011c716699
BLAKE2b-256 77a7f01570a84ced1c08a5d9f9a847f7da834cbbb3811ea6f7d51a8c973f6578

See more details on using hashes here.

Provenance

The following attestation bundles were made for ofiqpy-0.2.0.tar.gz:

Publisher: workflow.yml on AVHBAC/ofiqpy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ofiqpy-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: ofiqpy-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 50.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ofiqpy-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 45f9662f4c188b39f37b32161a6fdf68da6c43d24a0b942d271be1f7dc006338
MD5 eb3bead8f088f229528877302c640b0f
BLAKE2b-256 c54fa275d7b1479d00874bdf61448cebe4c7610d4e502571de42eaf5df40fcfe

See more details on using hashes here.

Provenance

The following attestation bundles were made for ofiqpy-0.2.0-py3-none-any.whl:

Publisher: workflow.yml on AVHBAC/ofiqpy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page