← all posts
// ocr · ocr-models

OCR models for tables and statements: choosing an OCR-capable model

Somebody on your team has lived through this. A statement-parsing pipeline looked flawless in the demo, shipped, and quietly attached a correctly-recognized digit to the wrong row. Nothing crashed. The output read clean. The reconciliation just stopped balancing, and nobody knew why until someone pulled the source page and found a number sitting one row off.

That's the shape of the problem people flatten into the word "OCR." An OCR engine, a layout-aware parser, and a vision-language model sit at different layers: one turns pixels into characters, one turns characters into structure, one reasons about what the structure means. Pick the wrong layer and you're asking a model to guess at exactly what it guesses worst.

For tables and statements, the workload is financial statements, schedules, price lists, lab results, multi-page tabular reports: a value means nothing without its row, column, and header attached. Faint rules, wrapped cells, repeated headers, indentation, negative-number conventions, dense small type are just what real statements look like. A vision-language model can genuinely help, linking a distant label to a value or rebuilding a broken table, but it can also replace an uncertain character with fluent-sounding language instead.

So match the candidate to script, layout, handwriting, resolution, output structure, and deployment constraints. Start with layout-aware OCR, table detection, and deterministic spreadsheet validation. Bring in a generative model only where it earns its keep: hard handwriting, irregular layout, semantic field linking, exceptions the deterministic stage can't clear. It has no business replacing a cheaper stage that already works.

keep a chain of custody for every character

Preserve before you interpret. Run a labeled page set through a classical OCR engine, a layout-aware parser, and an OCR-capable VLM side by side, with page and document identifiers assigned first. Every downstream fact should trace back through a record like this:

stagecapture
sourcehash, page, device
preprocessingcrop, dewarp, threshold, denoise
recognitionmodel, runtime revision
outputtext, regions, order, confidence
reviewfield, validation, reviewer change
costlatency, memory, spend

Never let normalization overwrite transcription. Where a character is genuinely ambiguous (an O or a 0, a decimal point, a diacritic) store what the recognizer saw and what the business rule proposed as two fields, not one that picked a winner.

Measure the right thing, too. Character and word error rate treat a dropped comma and a wrong account number as the same size mistake, and they are not. Add exact-match scoring for identifiers, dates, amounts, units, and score table reconstruction on its own: a model can nail every character and still misplace them.

fluent output is not verified output

The failure to design around is correctly recognized digits attached to the wrong row, column, or unit. Nothing about it looks broken. A model trained to continue plausible patterns will happily finish a damaged surname or total into something that looks normal, because that's its job. Picking a general VLM off a visual-quality leaderboard, when your acceptance gate is exact transcription, is the trap specific to this work.

Build an abstention path and mean it. Low-resolution regions, clipped pages, glare, unreadable handwriting, contradictory totals: these raise an exception, not a plausible guess. Confidence scores are inconsistent across systems and often poorly calibrated, so pair them with image-quality checks, format validators, cross-field arithmetic, and disagreement between passes.

Give reviewers provenance, not a transcript to retype. Store the page number and bounding polygon per field, and show the crop beside the proposed value. A person resolves an ambiguous digit in seconds when they see the source pixels; without that, review means re-scanning the page or hunting down the physical document.

When you call on a VLM, keep it on a short leash. Ask it to separate observation from interpretation, and keep schema validation and business rules for any write outside the model. Text printed inside the document is untrusted input, not an instruction. Split multi-page documents deterministically, attach identifiers first, and say whether a table continues across a boundary: let a model merge pages freely and two statements quietly become one.

Version model, preprocessing, dictionaries, and rules together, and replay a stratified set (clean pages, common noise, hard layouts, the fields you can't afford to miss) whenever one changes. Local deployment keeps documents under your control and gets cheaper at volume, but you carry storage, accelerator time, and upkeep yourself. Hosted APIs and frontier vision models buy elasticity and a higher exception ceiling, for upload time, retention terms, and per-page fees. Hybrid routing helps only when privacy rules are strict and escalation stays visible.

I still don't have a clean answer for the exception queue. Once abstention flags the genuinely hard pages, who reviews those, on what schedule, and what happens to a statement sitting half-verified for a week because nobody got to it. That part I've never seen a pipeline solve.

#ocr-models#document-ai#vision