There is a common assumption that warehouse OCR is a solved problem: point a camera at a label, get text, look it up. In practice the text you get back is fragmented, partially obscured, and occasionally wrong in ways that look right. The interesting work starts after the OCR step.
What raw OCR output actually looks like
A single physical label rarely arrives as a single string. It arrives as several fragments with bounding boxes, some duplicated, some cut off by the edge of the frame, some split across a fold or a shadow. Character confusions are routine: 0 and O, 1 and I, 5 and S, 8 and B.
So the first stage is not lookup, it is reconstruction, grouping fragments by their spatial relationship and rebuilding the label the way a person reading it would.
Why exact matching fails
Once you have a reconstructed label, the obvious move is to look it up in inventory. On real data, exact matching finds a disappointing fraction of cases, because a single misread character produces a miss rather than a near-miss.
In the matching engine we built for warehouse reconciliation, exact match is only the first of several strategies. It runs alongside prefix, suffix, and numeric-prefix matching, and a Levenshtein fuzzy search for cases where the reconstruction is close but not clean.
- Exact match, the label as reconstructed
- Prefix and suffix match, for labels truncated by the frame
- Numeric-prefix match, where the leading digits are reliable and the tail is not
- Fuzzy match, bounded edit distance for character confusions
The part that matters most: refusing to guess
Multiple strategies produce multiple candidates, and now you have a scoring problem. Each candidate gets scored across several signals: which strategy matched, how much of the label was recovered, the OCR confidence, and whether the item is plausibly in that location.
The critical rule is what happens when the top two candidates score too closely. A system that always returns its best guess will confidently assign stock to the wrong record, and nobody downstream will know. Ours declares ambiguity and escalates to a person instead. A no-match that a human resolves in twenty seconds is much cheaper than a wrong match discovered at stocktake.
Catching a different error for free
Once you know which record a label belongs to and where the photograph was taken, you can compare the two. That comparison catches a problem the manual process never surfaced: items that are correctly recorded but physically in the wrong bin.
This turned out to be one of the more valuable outputs of the system, and it was a side effect of doing the matching properly rather than a requirement anybody wrote down.
Traceability is a feature, not documentation
Every decision the engine makes emits evidence: the fragments it started from, the reconstruction, the candidates it considered, the score breakdown, and the outcome. Runs produce CSV summaries and per-image evidence packs.
This is what makes the system trustworthy in an audit and tunable in practice. When an analyst disagrees with a decision, you can see exactly which signal was wrong and adjust the weighting, rather than arguing about a black box.
What to check before starting
If you are considering this kind of project, the single most useful thing you can do first is run the OCR you already have over a sample of your worst images (poor lighting, partial labels, awkward angles) and look at the raw output. That tells you how much reconstruction work the project involves, which is the main driver of effort.