← all posts
// ocr · ocr-models

OCR models for forms and handwriting: capture quality before recognition

So no, a sharper prompt doesn't fix a blurry photo of a delivery slip. By the time a frame reaches the model, the pixels already decided what's recoverable: a check mark at the edge, a smudge that might be a decimal. Prompting comes after that, not before.

The pixel budget nobody prompts around

The workload: applications, surveys, checklists, delivery slips, forms marked up by hand. You're extracting printed labels, marked choices, handwriting, a signature standing in for presence, and the field-to-value link. What breaks capture is unglamorous: crossed-out text, touching characters, faint pencil, stray marks, notes outside the expected region. No inference-time trick invents detail the sensor never captured. The smallest character you care about needs enough clean pixels to survive before any model looks at it.

The pixels already decided what's recoverable before the model ever saw them.

Order of operations, not order of preference

Check blur, glare, clipping, skew, resolution, and completeness first, and reject or reacquire failures. Keep the file immutable, ID it, then run template registration, region cropping, printed OCR, and handwriting recognition, logging hash and preprocessing versions. Bring a generative model in only where it earns its keep: hard handwriting, an unmatched layout, a distant label-value link, an exception the deterministic stages can't resolve, never as a replacement. Character error rate weighs a dropped comma like a wrong account number, so track exact matches on dates and identifiers, and score field placement apart from transcription.

The failure that reads perfectly

What costs you here is quieter than garbled output: a legible value in the wrong field, or a mark read where none exists, both a model continuing a plausible pattern, turning a damaged surname or torn part number into something fluent and wrong. Build a real abstention path: low resolution, a clipped page, glare, unreadable handwriting, or totals that don't reconcile should raise an exception, not a guess. Confidence scores alone are poorly calibrated, so pair them with image-quality checks, format validators, and pass disagreement, and store the bounding polygon beside each field, so review means a crop beside the answer, not a page hunt.

What you don't let the model decide

A vision-language model earns its place tying a label to a distant value or explaining disagreeing totals, but keep it separating observation from inference, and every write behind schema validation outside the model: text on a form is data, not instructions, and treating it otherwise turns reconstruction into prompt injection. On multi-page batches, preserve order and header identity, never merge pages from different invoices, state whether a table continues past a page break, and version the model, preprocessing, and validation together, replaying clean, noisy, and impossible pages whenever one changes.

I run this locally when volume is high and steady: documents stay on hardware I control, and once storage and upkeep are paid, the marginal page is nearly free. What I give up is the exception-handling ceiling a hosted frontier model still holds, so I route the messy slice to an API rather than pretend a local stack will close that gap. That's the trade.

#ocr-models#document-ai#vision