E-3 with the calibrated lines: 66% at 95% precision with the text lane, 55% at 81% without, 2 false accepts against 8. The lane adds 11 pp of coverage while raising precision 14 pp, so the answer stands and the margin is wider than the audit's. The labels README pointed at evidence/image6_v2.json, which was a byte-identical duplicate of eval/labels/image6.json and is now removed; the README says so instead of describing a copy that no longer exists.
54 lines
3.2 KiB
Markdown
54 lines
3.2 KiB
Markdown
# Shelf label files
|
|
|
|
Ground truth for the identity evaluators (`code/eval_identity.py`,
|
|
`code/eval_live.py`) and for the evidence scripts in
|
|
`docs/research/2026-09-28-recognition-architecture/evidence/`.
|
|
|
|
{"image": "add/image6.jpg", "version": 2, "facings": [ ... ]}
|
|
|
|
`image` is the photo the boxes index into. `facings` is one row per detected
|
|
product facing, in that photo's own pixel coordinates.
|
|
|
|
## Row schema
|
|
|
|
| Field | Required | Meaning |
|
|
|---|---|---|
|
|
| `index` | yes | Row identity. Stable across label revisions, so a run's per-facing log joins to truth by `index`, never by array position. |
|
|
| `box` | yes | `[x1, y1, x2, y2]` in `image` pixels. |
|
|
| `label` | yes | Canonical SKU id (`sku_l01`), `unknown` for a facing that is not in the catalog, or `exclude` for a facing no lane can be scored on. |
|
|
| `source` | yes | How the label was decided. `v1-confirmed-visual` = the v1 label was checked against the package and kept; `visual-audit-2026-09-28` = the label was re-read from the package in the 2026-09-28 audit. |
|
|
| `v1_label` | yes | The label this row carried in v1. Kept so claims computed on v1 stay reproducible and the 26 corrections stay auditable. |
|
|
| `note` | when `label != v1_label` | Why the label changed. Also on a few unchanged rows that need a remark. |
|
|
| `match` | no | v1 provenance only: the field DECISION.md §3 reads as a match IoU, and as evidence that v1 labels were propagated from tag or box matching rather than read off packages. Values here are 0.0, 0.911, 1.0. No scorer reads it; it is carried through unchanged for traceability. |
|
|
|
|
`label` takes a canonical SKU id, `unknown`, or `exclude`. This file uses
|
|
`sku_l01`-`sku_l12`. `exclude` rows stay in the file so the facing inventory is
|
|
complete; every scorer drops them before computing a rate. The evaluators read
|
|
`index`, `box`, and `label`; the provenance fields are additive.
|
|
|
|
`image6.json` is the corrected v2 set: 111 rows, 109 scored (2 `exclude`), 64
|
|
in-catalog across 12 SKUs, 45 `unknown`. 26 labels changed from v1, and three
|
|
more changed on 2026-09-29: facings #46-48 were `unknown` with the note
|
|
"possibly what stock.csv calls l12", and the l12 reconciliation settled it, so
|
|
they now carry `sku_l12`. This file is the single copy: the evidence directory
|
|
used to hold a duplicate (`image6_v2.json`) and it was removed on 2026-09-29
|
|
after `cmp` showed the two byte-identical, because a copy that nothing reads is
|
|
a copy that drifts.
|
|
|
|
## Schema check
|
|
|
|
DECISION.md §7 sets the rule for every label file:
|
|
|
|
> Every label row carries `source`, `confidence`, and `labeler`. A label file
|
|
> without them fails a schema check.
|
|
|
|
The current file does not meet it. All 111 rows carry `source` and `v1_label`,
|
|
but none carries `confidence` or `labeler`: the file records where each label
|
|
came from and what it replaced, not a per-row certainty or a labeler name.
|
|
Inventing confidence values after the fact would be worse than the gap, so they
|
|
are absent rather than guessed.
|
|
|
|
Tier-2 labels must add both. `confidence` is the labeler's own certainty for
|
|
that row; `labeler` names the person or pass that produced it, because Tier 2 is
|
|
double-labelled and a disagreement has to be traceable to a pass. Tier 1
|
|
(`image6.json`) is dev-only and its numbers never ship, so it stays as it is.
|