product-recognition-demo/recognization/DEMO.md
kiyo9w e67ab8bfb4 chore: the film-making shortcut leaves the server, and failures stop hiding
From the deep review's hygiene list:

- The demo replay (a still recognition replayed as if it were live tracking) moves
  out of app.py into demo_replay.py, and every payload it produces is marked
  `synthetic: true`. It had been committed inside an unrelated feature commit, which
  made a film-making device look like part of the server.
- `/v1/health` reports the OCR engine and whether it is available. Without it an
  operator could not tell a broken OCR from a shelf with no readable tags.
- A failed OCR pass is counted and logged instead of swallowed: `TagService.stats()`
  now carries `passes_failed` and `last_pass_error`.
- The live classification budget goes back to the measured production defaults
  (16 in flight, 2 attempts); a demo walk over a nearly static shelf asks for more
  through `--live-inflight` / `--live-attempts` rather than silently changing the
  default for everyone.

162 tests pass.

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-25 01:30:16 +09:00

81 lines
3.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Running the demo
Two surfaces: the **web client** (open it in a browser) and the **iOS/Android app**
(scan screen). Both are clients of the same recognition server.
## 1. Start the server
```bash
cd recognization
YOLO_OFFLINE=1 .venv/bin/python code/app.py --port 8080 --classify-workers 8
```
Ready when `curl -s http://127.0.0.1:8080/v1/health` answers (about 25 s: the model
and the catalog load, then the OCR engine reports itself).
Flags that matter for a demo:
| Flag | Why |
| --- | --- |
| `--classify-workers 8` | More parallel classification; the demo's bottleneck. |
| `--host 0.0.0.0` | Only if a phone or iPad on the LAN must reach it (set `DORAYAKI_API_TOKEN` too). |
| `--no-tags` | Disables price-tag OCR entirely if it is fighting for CPU. |
| `DORAYAKI_OCR=none` | Same, via environment. |
## 2. The web client
Open <http://127.0.0.1:8080>.
- **Live** — pick a camera (or “Video file…”), press Start. Boxes appear as
products are recognised, with name and price; teal boxes mark the shelf-edge
price tags; amber means “check this”; red marks empty shelf space.
- **Photo** — a still shelf image: boxes paint immediately, identities fill in,
the algorithm selector re-classifies, and tapping a product opens the card with
the catalog photo, stock, and the tag reading compared against the catalog.
## 3. The app (iOS simulator, no camera needed)
The app can drive a **synthetic store walk**: the server renders a virtual camera
sweeping a real shelf photo — pan a row left to right, step up, pan back — so the
scan screen behaves like an employee walking the shelf.
Start the server on the port the app expects (8090 is the Debug default; 8097 is
what the verification scripts used — pass the override if you change it):
```bash
YOLO_OFFLINE=1 .venv/bin/python code/app.py --port 8090 --host 127.0.0.1 --classify-workers 8
```
Then run the app in the simulator and open **Scan**. Press the scan control: the
stage shows the walk moving, green boxes with names appear, teal tag boxes carry
prices, and tapping a product opens the card.
On a real device, replace the walk with the camera: the app uses the device camera
and the same server (a LAN IP needs HTTPS or an ATS exception — see
`docs/API.md`).
## 4. The demo configuration (measured)
Everything below was measured on this machine, 2026-09-24, one client, 1280×720
frames, the synthetic walk:
| Setting | Result |
| --- | --- |
| live method `orb` | **7.2 results/s, 178 labelled tracks, 21 distinct SKUs, first label 0.7 s** |
| live method `hybrid` | 1.4–9.9/s depending on load, 4–13 tracks, first label 3–5 s |
| walk `pan=0.02` | a row sweeps in ~8 s — reads like a person |
| walk `pan=0.06` | ~3 s per row — a time-lapse |
| OCR cadence (live) | 1 rail band every 30 frames; more than that drops the frame rate |
So: **ORB for live labelling, Hybrid for “Show matching”** (tap-to-inspect), and
the slower walk pace. The method menu in both clients switches between them live.
## 5. What to say, honestly
Working today: live detection and tracking, product identity with names and
prices, price-tag reading and the tag-vs-catalog comparison, empty-shelf gaps,
tap-to-inspect with the catalog photo and stock, and the walk.
Not built yet: configurable shelf rules (facing counts, brand blocks), the
fix → rescan → verify loop, and a head-office dashboard. Do not claim those on
camera.