OCR models for scanned archives: preprocessing for OCR models
the scan is the only truth you get
A scanned archive gives you one fixed set of images and nothing else: you can't re-photograph a faded ledger page, so every decision works forward from what the scan contains. The material is books, correspondence, reports, and historical records off paper or microfilm: skew, bleed-through, stains, archaic typefaces, marginal notes, inconsistent scanning across decades. What you owe the archive is searchable text, in reading order, tied to a page, with the uncertain bits marked as uncertain.
My rule: a transformation earns its place if it makes the page more legible, and it's out if it changes what the page says. Deskewing, contrast correction, and denoising touch visibility, not content. A generative OCR or vision-language model is different: trained to produce plausible text, and plausible isn't accurate. Start cheap: a conventional OCR engine, language packs, layout segmentation, and bring in a generative model only where it earns its cost, bad handwriting, irregular layouts, fields needing semantic association. Don't let it replace stages that already work.
Keep the source file untouched and give every page a stable identifier first. Version each processing step, orientation, crop, dewarp, denoise, threshold, contrast, and score every version against the untouched original, never the last one. I log this per page:
source hash, page id, capture device
crop / dewarp / threshold / denoise versions
OCR or VLM model + runtime revision
raw text, regions, reading order, confidence
If a character is ambiguous, an O that could be a 0, a decimal that could be a stain, store what the recognizer saw next to what a business rule proposes. Never let the second overwrite the first.
confident garbage is the failure that costs you
The failure nobody budgets time for isn't garbled output, that gets caught fast. The dangerous case is clean, plausible text that quietly replaces an unfamiliar surname, a faint date, or a part number with something familiar-looking, because a model continuing a damaged sequence reaches for the likely completion, and likely is the wrong criterion when you're transcribing evidence rather than predicting the next word. The trap here is tuning the pipeline to look clean, at the cost of the decimal point or the hand-drawn box around a number.
Character and word error rate are fine as a floor, but they'll report a healthy run while it mangled an account number, since a missing comma and a wrong digit score alike. Add exact-match checks on the fields that matter, identifiers, dates, amounts, units, warnings, and score table geometry and field association separately for structured documents.
Build an abstention path that's easy to trigger, hard to bypass:
- low-resolution or clipped regions raise a flag, not a guess
- glare, unreadable handwriting, and contradictory totals do the same
- confidence scores combine with image-quality checks and format validators, since they're poorly calibrated alone
- cross-field arithmetic and known dictionaries catch what confidence misses
- disagreement between two recognition passes on one region counts too
Store the bounding polygon for every field that matters and show the reviewer the crop beside the proposed value: a quick glance instead of retyping the document.
let the model read, not decide
A vision-language model earns its place connecting a label to a value elsewhere on the page, piecing a table back together after a fold split it, or explaining why two totals disagree. Ask it to separate observation from inference, and keep the two visibly apart. Anything writing to a database needs schema validation and business rules living outside the model. Full stop. Text printed on a scanned page is untrusted input: a document that reads like a command isn't asking the model to change its extraction behavior or call a tool.
Multi-page work needs its own discipline. Preserve page order and repeated-header identity; don't hand the model an arbitrary page bundle and expect it not to merge invoices or statements. Split documents deterministically, attach identifiers, and state whether a table may continue across a page boundary.
One rule sits under all three sections: keep the raw image, prefer reversible transformations, and compare recognition output rather than appearance. When a model or a validation rule changes, replay a fixed, stratified test set, clean pages, noise, hard layouts, critical fields, a few impossible ones, so you know what moved. Local deployment keeps documents under your control and gets cheaper as volume grows, but you carry storage, backup, and accelerator upkeep; a hosted API or frontier model buys elasticity and more headroom for exceptions, at the cost of upload time, retention terms, residency, and per-page fees. Routing by sensitivity works, as long as the handoff stays visible and logged.
I'd still rather trust this pipeline than a slicker one that produces prettier paragraphs. But provenance and abstention only tell you where the evidence is thin; they don't thicken it, and a badly imaged page stays a badly imaged page no matter how carefully you log the fact.