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 |
||
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 |
|
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 |
|---|---|
|
A full image. The largest face is detected, then cropped and compressed. |
|
A full image together with one of its faces, already detected. The face is cropped and compressed without running the detector again. |
|
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 )