# identity-bbox The coordinate space of a vision character box, and what reads it. ## A vision `bbox` arrives on gemma's 0-1000 grid, and `/vision` converts it to pixels {#bbox-is-normalized} **Closed, 2026-08-12.** `build_detect_prompt` asks for a "pixel bounding box". The model answers on its own normalized grid regardless. Measured over all 113 detections of job `778297bc`, read straight from `/review/identity`: | test | result | | --- | --- | | boxes with `x2` past the 900px panel width | **47 of 113** | | boxes with `y2` past 1000, on panels 1257 to 2307px tall | **0 of 113** | | boxes clamped at exactly 1000 | 21 in x, 5 in y | | coordinate range over every box | `[0, 1000]` | Pixels cannot behave that way. A person standing in the lower half of a 2307px panel needs `y2` near 2000, and it never once exceeds 1000. Consumed as pixels the boxes collapse into the top-left corner of the panel. Four consumers were reading them: * `worker_identity._crop_bbox` at `worker_identity.py:200`, which embeds the crop. This is why a crop of a speech balloon's edge matched `Choi Haeseon` at 0.9. * `_pair_faces_to_present` in `worker_vision.py`, which compares real detector face boxes, in pixels, against these. The gate could almost never pass, which is the mechanism behind the 7 `unknown` results out of 7 `som_face` lines already recorded at `worker_vision.py:169`. * the set-of-mark boxes drawn for attribution. * the review UI, which crops client-side off the panel PNG. `/vision` now calls `_bbox_to_pixels(characters, w, h)` before returning, so all four see pixels and no consumer needs to know the grid existed. Verified by drawing the converted boxes on panel 7. Five of six land on their subject, including `person_5`, who is Seonho in the foreground and had no identity. `person_1` still frames a window mullion with nobody in it, which is `#extras-as-cast`, not this. The prompt text still says "pixel bounding box". Rewording it changes what the model emits and needs a GPU run to re-verify, so the boundary converts instead. The `ponytail:` note on `_bbox_to_pixels` records that. It also records the trap: a model that really answered in pixels would be scaled down here. **Consequence: every assignment in the registry came from a wrong crop.** The existing embeddings and `ref_image_uris` are enrolled on balloons and window frames. Re-running identity is what makes the registry mean anything. The anonymous-identity and extra-versus-cast work cannot be judged until that rerun happens.