cat_full's *_shelf.jpg views are crops of add/image6.jpg itself - template matching puts each one back at 0.998-0.999 confidence - so committing them reintroduced the evaluation photo as a catalog, which is the leak the audit removed from stock-lopia. cat_pack is the same views without the shelf copies. Both are regenerated by lfo_setup.py from stock-lopia and the labels, so the evidence stays reproducible without the repository carrying the leak. Verified after removal: lfo_setup.py rebuilds all 16 views. |
||
|---|---|---|
| .. | ||
| .gitignore | ||
| an2.py | ||
| analyze.py | ||
| diag.py | ||
| dino_scale.py | ||
| distract.py | ||
| fuse_eval.py | ||
| image6-v1-labels-overlay.jpg | ||
| image6_v2_lfo.json | ||
| lfo_setup.py | ||
| ocr_exp.py | ||
| ocr_fuse.py | ||
| README.md | ||
| scale.py | ||
| sheet.py | ||
| variants.py | ||
Evidence scripts (2026-09-28 audit)
Read-only against product code: every script imports from code/ and writes
only into this folder. Run from recognization/ with .venv/bin/python.
eval/labels/image6.json is the corrected image6 label set (26 of 111 v1 labels
changed; every row carries v1_label, source, and a note where changed).
image6-v1-labels-overlay.jpg shows the v1 labels on the shelf; green = catalog
label, red = unknown. sheet.py regenerates per-SKU contact sheets.
| Step | Command (prefix E=docs/research/2026-09-28-recognition-architecture/evidence) |
Produces |
|---|---|---|
| Original matcher, both catalogs, full/live/live-with-unscaled-boxes | .venv/bin/python $E/diag.py --stock stock-lopia-clean --labels $E/../../../eval/labels/image6.json [--live] [--bug] --out $E/run_stock-lopia-clean_<full|live|livebug>.pkl (repeat with --stock stock-lopia) |
run_*.pkl |
| Score them under v1 or v2 labels | .venv/bin/python $E/analyze.py <labels.json> $E/run_*.pkl |
identity top-1, argmax, current gate |
| Matcher variants | .venv/bin/python $E/variants.py --stock stock-lopia-clean --labels $E/../../../eval/labels/image6.json [--live] --scales 200,400 --root --geom affine --out $E/v_ms_root_aff_<full|live>.pkl (also --tmpl-h 250/400, no flags = raw) |
v_*.pkl |
| Variant ranking + open-set frontier | .venv/bin/python $E/an2.py $E $(basename -a $E/v_*.pkl) (LABELS=image6_v2_lfo.json for the leave-facing-out runs) |
correct at 100/95/90 % precision |
| Leave-facing-out catalog | .venv/bin/python $E/lfo_setup.py, then variants.py --stock $E/cat_<pack|full> --labels $E/image6_v2_lfo.json --scales 200,400 --root --geom affine [--live] --out $E/lfo_cat_<pack|full>_<full|live>.pkl |
lfo_*.pkl |
| Unrelated-shelf distractors | YOLO_OFFLINE=1 .venv/bin/python $E/distract.py stock-lopia-clean $E/cat_full |
distract.pkl |
| Catalog growth, exhaustive vs descriptor index | YOLO_OFFLINE=1 .venv/bin/python $E/scale.py |
stdout |
| DINO retrieval under growth | YOLO_OFFLINE=1 .venv/bin/python $E/dino_scale.py |
stdout |
| OCR read-rate | .venv/bin/python $E/ocr_exp.py |
ocr.pkl |
| OCR signatures, then fusion | .venv/bin/python $E/ocr_fuse.py && .venv/bin/python $E/fuse_eval.py |
sig.pkl, stdout |
| Per-SKU contact sheets + the labelled shelf | .venv/bin/python $E/sheet.py <outdir> |
gt_<label>.jpg, shelf_labels.jpg |
Timings in DECISION.md come from scale.py (single process). The other
scripts ran up to ten processes at once, so their ms figures are relative only.
Verified 2026-09-28
Every command above was run from recognization/ and produced its listed
output. Two rows were wrong as written:
- The table said
python; thepythonon this machine's PATH has nocv2, so every row failed on import. It is.venv/bin/python. an2.pytakes the folder and then file names inside it, sov_*.pklexpanded in the working directory, where those files do not live. It is$(basename -a $E/v_*.pkl).
sheet.py was missing from the table. It takes its output directory as a
positional argument, not a flag: sheet.py --help reads --help as a
directory name, writes nothing, and still exits 0. analyze.py and an2.py
with no arguments raise IndexError; neither validates its own usage.
v1 labels are no longer a file on disk — eval/labels/image6.json is the v2
set. To score a run under v1, rebuild it from the v1_label field:
.venv/bin/python -c "import json;d=json.load(open('$E/../../../eval/labels/image6.json'));\
[f.update(label=f.pop('v1_label')) for f in d['facings']];\
json.dump(d,open('/tmp/image6_v1.json','w'),ensure_ascii=False)"
That reconstruction reproduces DECISION.md's v1 numbers exactly: analyze.py
gives ungated top-1 26/35 at both resolutions and the current gate 24/35 full,
23/35 live (§2 row 15, F-01).