feat: a multi-view embedding gallery, because one template per SKU cannot work
The user's objection was right and it changed the design: the tag channel is
sparse in the real world (measured: 0 tags readable at ~2 m on the main shelf), so
packaging recognition has to carry identity. Measured on a 12-class, 57-facing
evaluation set read off the demo shelf, the packaging channel as shipped cannot:
views per SKU embedding top-1 shipped matcher top-1
1 57 % 33 %
2 72 % 27 %
3 75 % 20 %
4 76 % 5 %
Two things follow. First, two views per SKU is where most of the gain is - that is
the enrollment spec (a first scan already produces several facings per product).
Second, the matcher gets *worse* with more views, because its raw inlier score is
not calibrated to be aggregated and it cannot express two views of one SKU at all:
it keys templates by filename.
So identity becomes retrieval: `gallery.py` embeds every enrolled view with DINOv2
ViT-S/14, scores a SKU by its best view, and rejects when nothing is close enough
(an unknown product must come back unknown, not as the nearest stranger). Measured
with held-out views - the gallery never contains its own queries - 2 views per SKU
over 12 SKUs gives 69 % top-1 with rejection working, and the threshold moves the
rejection line.
It is affordable in the live loop only on the GPU: 159 ms per crop on CPU versus
3.6 ms on the M5's MPS, and a live frame only needs its new tracks embedded.
157 tests pass; test_gallery.py covers the retrieval contract (best view wins,
several views are one answer, strangers are rejected) with injected embeddings so
it needs no torch.
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
BIN
recognization/stock-lopia/sku_l01_1.jpeg
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
recognization/stock-lopia/sku_l01_2.jpeg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
recognization/stock-lopia/sku_l02_1.jpeg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
recognization/stock-lopia/sku_l02_2.jpeg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
recognization/stock-lopia/sku_l02_3.jpeg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
recognization/stock-lopia/sku_l03_1.jpeg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
recognization/stock-lopia/sku_l03_2.jpeg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
recognization/stock-lopia/sku_l03_3.jpeg
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
recognization/stock-lopia/sku_l04_1.jpeg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
recognization/stock-lopia/sku_l04_2.jpeg
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
recognization/stock-lopia/sku_l04_3.jpeg
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
recognization/stock-lopia/sku_l05_1.jpeg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
recognization/stock-lopia/sku_l05_2.jpeg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
recognization/stock-lopia/sku_l05_3.jpeg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
recognization/stock-lopia/sku_l07_1.jpeg
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
recognization/stock-lopia/sku_l07_2.jpeg
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
recognization/stock-lopia/sku_l07_3.jpeg
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
recognization/stock-lopia/sku_l09_1.jpeg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
recognization/stock-lopia/sku_l09_2.jpeg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
recognization/stock-lopia/sku_l09_3.jpeg
Normal file
|
After Width: | Height: | Size: 17 KiB |