File size: 2,081 Bytes
1b4ed07
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# Copyright 2026 AutomatosX
# SPDX-License-Identifier: AGPL-3.0-only
# Modified 2026-10-17 for v1.2; prior component notices are in NOTICE.
"""Canonical JSON for unqualified local detections.

Both the local ONNX runner and the local PyTorch runner serialize through
this function. The payload is not a published ``PageStructure``.
"""

from __future__ import annotations

from collections.abc import Sequence

from ax_doclayout.artifact import canonical_json_bytes
from ax_doclayout.contract import Element

LOCAL_DETECTION_SCHEMA = "ax-doclayout.local-detection/1"
LOCAL_QUALIFICATION = "local-bundle-unqualified"
# Shared unqualified serialization. PyTorch and ONNX agree well inside
# these places; the published parity gate is coarser (0.5 px, 0.001 score).
SCORE_DECIMALS = 4
BOX_DECIMALS = 3


def _places(value: float, places: int) -> float:
    return round(float(value), places)


def canonical_local_detection_bytes(
    *,
    page_index: int,
    width_px: int,
    height_px: int,
    elements: Sequence[Element],
    threshold: float,
) -> bytes:
    """Serialize one unqualified page detection with sorted keys."""

    payload = {
        "elements": [
            {
                "bbox": {
                    "x_max": _places(element.bbox.x_max, BOX_DECIMALS),
                    "x_min": _places(element.bbox.x_min, BOX_DECIMALS),
                    "y_max": _places(element.bbox.y_max, BOX_DECIMALS),
                    "y_min": _places(element.bbox.y_min, BOX_DECIMALS),
                },
                "class_id": int(element.class_id),
                "class_name": element.class_name,
                "confidence": _places(element.confidence, SCORE_DECIMALS),
                "id": element.id,
            }
            for element in elements
        ],
        "height_px": int(height_px),
        "page_index": int(page_index),
        "qualification": LOCAL_QUALIFICATION,
        "schema_version": LOCAL_DETECTION_SCHEMA,
        "threshold": float(threshold),
        "width_px": int(width_px),
    }
    return canonical_json_bytes(payload)