Face compression

The FaceCompressor module compresses a portrait into a compact buffer, and decompresses it back into an image. It is typically used to embed a portrait into a constrained storage medium (e.g., a QR code, an NFC chip, a barcode) where only a small number of bytes is available.

Two independent compression approaches are available:

AI compression

WebP compression

Functions

compressAi / decompressAi

compressWebp / decompressWebp

Output size

Fixed: always exactly 500 bytes.

Configurable: fits within a caller-supplied byte budget (default 800 bytes), at the highest quality that satisfies it.

Portrait crop

Fixed 192x256 (width x height) Bioseal portrait alignment.

Configurable output size (default 84x112) and face placement.

Required models

FaceCompressionEncoder1A and/or FaceCompressionDecoder1A (see Face compression models), plus a FaceDetector model when face detection is performed internally.

A FaceDetector model when face detection is performed internally. Compression and decompression use the standard WebP codec directly: no dedicated model is needed.

Best suited for

Applications requiring the best reconstructed image quality at a smaller, constant payload size.

Applications requiring an open, standard image format, at the cost of a lower reconstructed image quality and a variable payload size.

Compression entry points

Both approaches expose three entry points, which differ only in how much of the pre-processing the caller has already performed:

Function

Expected input

compressAi / compressWebp

A full image. The largest face is detected, then cropped and compressed.

compressAiFromDetectedFace / compressWebpFromDetectedFace

A full image together with one of its faces, already detected. The face is cropped and compressed without running the detector again.

compressAiFromCroppedPortrait / compressWebpFromCroppedPortrait

An already cropped portrait, compressed directly.

The FromDetectedFace variants are the preferred entry point for applications that already run a FaceDetector on the image, as they avoid a redundant second detection.

Important

Loading a FaceDetector model is required only by compressAi and compressWebp, which perform face detection internally. The FromDetectedFace and FromCroppedPortrait variants do not.

Warning

The face passed to the FromDetectedFace variants must be expressed in the coordinate system of the image it is passed with. When it was obtained on a downscaled copy of that image, as recommended in Face detection, rescale it back with DetectedFace.rescale first.

AI compression

compressAi detects the largest face in the image, aligns and crops it into a 192x256 Bioseal portrait, then runs the FaceCompressionEncoder1A model to produce a fixed-size 500-byte template. decompressAi runs the FaceCompressionDecoder1A model to reconstruct the 192x256 portrait from that template.

If the face has already been detected, compressAiFromDetectedFace skips face detection, performing only the alignment and compression. If the portrait is already cropped and aligned to 192x256, compressAiFromCroppedPortrait skips face detection and alignment, compressing it directly.

Important

FaceCompressionEncoder1A is required for compression, and FaceCompressionDecoder1A for decompression. Loading both is only necessary if your application performs both operations.

WebP compression

compressWebp detects the largest face in the image and crops it using an eye-distance-based placement, distinct from the Bioseal portrait alignment used by AI compression. The face placement is controlled by three parameters, forwarded to DetectedFace.getPortraitBounds:

Parameter

Description

eyeImageWidthRatio

Ratio between the interocular distance and the crop width. Must be in the range ]0;1[. Default recommended value is 0.40.

eyeImageHeightRatio

Ratio between the eye-to-top distance and the crop height. Must be in the range ]0;1[. Default recommended value is 0.45.

imageRatio

Ratio between the crop height and width. Default recommended value is 1.3333334 (4:3).

The crop is then resized to outputWidth x outputHeight (default 84x112), and compressed to WebP: the quality (a value from 1 to 100) is searched automatically to find the highest value whose encoded size still fits within byteBudget (default 800 bytes).

Warning

A budget that is too tight relative to outputWidth/outputHeight may be unreachable even at the lowest WebP quality, in which case the function fails instead of returning an oversized buffer. Should this occur, raise the budget or reduce the output size.

decompressWebp is a plain WebP image decode (the format is auto-detected from the buffer): unlike decompressAi, no model is required, and it can decode any standards-compliant WebP buffer, not only those produced by compressWebp.

If the face has already been detected, compressWebpFromDetectedFace skips face detection, performing only the crop and compression. If the portrait is already cropped, compressWebpFromCroppedPortrait skips face detection and cropping, compressing it directly.

Full sample

The example below demonstrates both compression approaches on the same image:

license_path = "C:\ProgramData\id3\id3FaceToolkit_v10.lic"
ai_models_folder = "models/"
image_path = "data/placeholder.jpg"

# [start]
import id3face as id3

def compress_ai_roundtrip(compressor: id3.FaceCompressor, image: id3.Image) -> id3.Image:
    """
    compressor: id3.FaceCompressor = ... # Previously initialized compressor module
    Requires a FaceDetector model and the FaceCompressionEncoder1A/FaceCompressionDecoder1A models.
    """
    # Detects the face, aligns/crops it into a Bioseal portrait (192x256),
    # and compresses it into a fixed-size 500-byte template.
    template = compressor.compress_ai(image)

    # Decompresses the template back into a 192x256 portrait image.
    return compressor.decompress_ai(template)


def compress_webp_roundtrip(compressor: id3.FaceCompressor, image: id3.Image) -> id3.Image:
    """
    compressor: id3.FaceCompressor = ... # Previously initialized compressor module
    Only requires a FaceDetector model (no compression model needed).
    """
    # Detects the face, crops it using a tighter, eye-distance-based placement,
    # resizes it to 84x112, and searches for the highest WebP quality whose
    # size still fits within the 800 byte budget.
    buffer = compressor.compress_webp(
        image,
        84, 112,                # output_width, output_height
        800,                    # byte_budget
        0.40, 0.45, 1.3333334,  # eye_image_width_ratio, eye_image_height_ratio, image_ratio
    )

    # Decodes the WebP buffer back into a portrait image (a standard image
    # decode, no model needed).
    return compressor.decompress_webp(buffer)

def compress_from_detected_face(
    compressor: id3.FaceCompressor, detector: id3.FaceDetector, image: id3.Image
) -> bytearray:
    """
    compressor: id3.FaceCompressor = ... # Previously initialized compressor module
    detector: id3.FaceDetector = ...     # Previously initialized detector module
    """
    # Downscale the image to respect the detector range of ~[16-400px], and keep
    # the ratio to bring the detected face back into the full-resolution referential.
    image_downscaled = image.clone()
    ratio = image_downscaled.downscale(384)
    detected_face = detector.detect_faces(image_downscaled).get_largest_face()
    detected_face.rescale(1 / ratio)

    # The face is already detected, so compression reuses it instead of running
    # the FaceDetector model a second time.
    return compressor.compress_webp_from_detected_face(
        image, detected_face,
        84, 112,                # output_width, output_height
        800,                    # byte_budget
        0.40, 0.45, 1.3333334,  # eye_image_width_ratio, eye_image_height_ratio, image_ratio
    )

See also