product-recognition-demo/recognization/code
kiyo9w b451e7096f feat: a shelf map, so a facing outlives the track id that found it
The camera moves and the shelf does not, but every measurement so far treats a
frame as the world: a facing is "a track id", and that id dies the moment the camera
pans away and comes back. Label inheritance, drift checks and restart counters were
each correct fixes for that, and all of them are symptoms.

`shelf_map.py` keeps a per-session map of the shelf plane. Frames are registered by
their content shift, detections are placed in shelf coordinates, and a detection that
lands where a facing already is merges into it - so identity votes and tag readings
pool on the physical facing.

Measured, and reported honestly:

- Registration is exact on the synthetic walk: 0.01 px median error against the demo
  camera's own offsets, over 23 consecutive pairs, with both phase correlation and
  ORB + RANSAC. That validates the harness, not the method - the walk is a pure
  translation of one photograph. Real video needs step 1's footage.
- Pooling works: a facing seen 15 times across 2 track ids reports one identity at
  1.00 agreement.
- De-duplication is NOT yet better than the tracker: 179 facings against 156 track
  ids, where the shelf holds roughly 70. Both over-count, the map slightly more.

Two bugs were found by measuring, and both were silent: the content shift is the
negation of the camera's motion (getting it backwards turned ~60 facings into 857),
and matching purely by box overlap lets jitter split a facing (210 facings, 103 of
them seen once; matching by track continuity first brought it to 179 with 38).

175 tests pass.

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-25 01:54:38 +09:00
..
web feat: price-tag UI, still-image tag passes, and honest tag evidence 2026-09-24 14:11:23 +09:00
__init__.py Initial commit for push folder 2026-09-18 09:13:53 +09:00
app.py feat: record a live session so it can become data 2026-09-25 01:34:15 +09:00
bench_engine.py feat: recognition engine and session tracker for multi-client serving 2026-09-24 11:52:59 +09:00
bench_identity.py feat: a multi-view embedding gallery, because one template per SKU cannot work 2026-09-24 23:43:27 +09:00
bench_shelf_map.py feat: a shelf map, so a facing outlives the track id that found it 2026-09-25 01:54:38 +09:00
benchmark.py Initial commit for push folder 2026-09-18 09:13:53 +09:00
demo.py perf: bound OCR so a walking scan stays real-time, and add walk pacing 2026-09-24 18:14:32 +09:00
demo_replay.py chore: the film-making shortcut leaves the server, and failures stop hiding 2026-09-25 01:30:16 +09:00
detector.py refactor: make the matcher and detector safe for concurrent clients 2026-09-24 11:43:24 +09:00
download_stock.py Initial commit for push folder 2026-09-18 09:13:53 +09:00
empty_shelf_detector.py Initial commit for push folder 2026-09-18 09:13:53 +09:00
engine.py chore: the film-making shortcut leaves the server, and failures stop hiding 2026-09-25 01:30:16 +09:00
fast_test.py Initial commit for push folder 2026-09-18 09:13:53 +09:00
feature_matcher.py feat: recognition server API, reference stream client, and live label memory 2026-09-24 12:31:17 +09:00
gallery.py feat: a multi-view embedding gallery, because one template per SKU cannot work 2026-09-24 23:43:27 +09:00
gui_app.py Initial commit for push folder 2026-09-18 09:13:53 +09:00
identity.py feat: identity decision contract and session-local observation model 2026-09-24 11:43:41 +09:00
inventory.py Initial commit for push folder 2026-09-18 09:13:53 +09:00
live.py chore: the film-making shortcut leaves the server, and failures stop hiding 2026-09-25 01:30:16 +09:00
observe.py feat: identity decision contract and session-local observation model 2026-09-24 11:43:41 +09:00
ocr.py feat: OCR engine, price-tag geometry, and the cached tag pass 2026-09-24 13:52:15 +09:00
orb.py Initial commit for push folder 2026-09-18 09:13:53 +09:00
pipeline.py feat: identity decision contract and session-local observation model 2026-09-24 11:43:41 +09:00
reconcile.py fix: a tag may not accuse on weak evidence, nor name a distant product 2026-09-25 01:30:03 +09:00
record.py feat: record a live session so it can become data 2026-09-25 01:34:15 +09:00
shelf_map.py feat: a shelf map, so a facing outlives the track id that found it 2026-09-25 01:54:38 +09:00
stream_client.py feat: recognition server API, reference stream client, and live label memory 2026-09-24 12:31:17 +09:00
suft.py Initial commit for push folder 2026-09-18 09:13:53 +09:00
tag_cards.py fix: the number on the tag is the regular price, and a price must be corroborated 2026-09-25 01:29:46 +09:00
tags.py fix: the number on the tag is the regular price, and a price must be corroborated 2026-09-25 01:29:46 +09:00
test.py Initial commit for push folder 2026-09-18 09:13:53 +09:00
test_api.py test: defend the live session and the server API 2026-09-24 12:44:54 +09:00
test_demo.py feat: a synthetic store walk, and the live tuning it forced out 2026-09-24 18:09:23 +09:00
test_empty.py Initial commit for push folder 2026-09-18 09:13:53 +09:00
test_engine.py test: defend engine and tracking contracts 2026-09-24 12:43:32 +09:00
test_gallery.py feat: a multi-view embedding gallery, because one template per SKU cannot work 2026-09-24 23:43:27 +09:00
test_image.py Initial commit for push folder 2026-09-18 09:13:53 +09:00
test_live.py test: the live tag fixture carries a tax-included price 2026-09-25 01:30:28 +09:00
test_observe.py feat: identity decision contract and session-local observation model 2026-09-24 11:43:41 +09:00
test_ocr_tags.py fix: the number on the tag is the regular price, and a price must be corroborated 2026-09-25 01:29:46 +09:00
test_real_model.py docs: API contract, README for the server and live mode, real-model test 2026-09-24 12:46:54 +09:00
test_reconcile.py fix: a tag may not accuse on weak evidence, nor name a distant product 2026-09-25 01:30:03 +09:00
test_record.py feat: record a live session so it can become data 2026-09-25 01:34:15 +09:00
test_shelf_map.py feat: a shelf map, so a facing outlives the track id that found it 2026-09-25 01:54:38 +09:00
test_suite.py Initial commit for push folder 2026-09-18 09:13:53 +09:00
test_tag_cards.py fix: the number on the tag is the regular price, and a price must be corroborated 2026-09-25 01:29:46 +09:00
test_tag_identity.py fix: a tag may not accuse on weak evidence, nor name a distant product 2026-09-25 01:30:03 +09:00
test_tracking.py test: defend engine and tracking contracts 2026-09-24 12:43:32 +09:00
tracking.py fix: use the tracker imports that exist in ultralytics 8.4.153 2026-09-24 13:36:50 +09:00
train.py Initial commit for push folder 2026-09-18 09:13:53 +09:00
yolo_adapter.py feat: identity decision contract and session-local observation model 2026-09-24 11:43:41 +09:00