HighVRAM Hardware Watch

Turn a scanned PDF into searchable text locally

Turn an image-only PDF into a searchable PDF and a plain-text copy, then check whether the names and numbers survived. The actual run below produced a useful result and one wrong identifier. You can reproduce it with existing local OCR tools and see why a searchable document still needs review.

Download the OCR practice pack

The pack includes two fictional workshop pages, original text, an answer key, the untouched OCR output, a reviewed text copy, a checker and the exact tested commands.

Tested setup: Debian 13 cloud workspace, OCRmyPDF 16.7.0 and Tesseract 5.5.0. macOS and Windows are unverified.

1. Check your existing tools

Unzip the package and open a terminal in the extracted folder. This walkthrough assumes an existing Linux shell with OCRmyPDF, Tesseract, Poppler’s pdftotext and Python 3 already available. Run:

ocrmypdf --version
tesseract --version
tesseract --list-langs
pdftotext -v
python3 --version

The language list must include eng. If a command is missing, stop and use the official OCRmyPDF installation guide and Tesseract language-data instructions for your system. The package installs nothing and starts no service. Online instructions may cover newer releases than the versions tested here.

This exercise uses command-line OCR and requires no account, chat model or GPU setup.

2. Check the download and answer checker

sha256sum -c SHA256SUMS
python3 -m unittest -v test_validator
python3 validate.py expected/expected-text.txt

Expect OK for the listed file hashes, 14 passing tests and a final status of pass. The test cases include deliberately authored wrong values and ordering changes so the checker itself is tested. They are separate from the actual OCR results.

3. Convert the image-only input

The supplied input/scanned-inventory.pdf was made by rasterizing an original fictional workshop inventory at 300 dpi. It contains only page images, with no hidden original text layer. No physical scanner was used. OCR receives this image-only file; the original text and answers are kept separate.

bash run_ocr.sh

The script creates a new my-run folder, checks that the supplied input has no extractable text, saves your versions and input hash, runs OCR, extracts text back from the result and checks both text outputs. If my-run already exists, preserve it and use bash run_ocr.sh my-run-2 instead.

The OCR command inside that script is:

ocrmypdf --language eng --jobs 1 --output-type pdf --optimize 0 \
  --sidecar my-run/ocr.txt input/scanned-inventory.pdf \
  my-run/searchable-inventory.pdf

This selects English and one worker, writes an ordinary PDF with searchable text, and avoids optional image optimization. The sidecar is the recognized plain text. The checker reads the answers after recognition. The OCRmyPDF cookbook explains these options; OCRmyPDF invokes the Tesseract OCR engine.

4. Check names, numbers and reading order

Open my-run/searchable-inventory.pdf and search for Cedar workstation. Both page images should still look like the input. Then read my-run/ocr.txt, my-run/searchable-extracted.txt and the two validation JSON reports. The checker compares the complete text in page order, retaining case and punctuation while ignoring whitespace differences.

The supplied Linux run completed successfully, but one of 34 specified field checks failed. Page one’s printed document ID HV-OCR-01 became HV-OCR-0O1, with an extra capital O after the zero. That error appears in both the raw text and the PDF’s hidden text layer. The visible page still shows the correct ID.

The other 33 field checks passed, and the three inventory records plus six numbered steps stayed in the correct order. The full-text comparison found no other non-whitespace difference. A fresh second run returned the same raw text.

  • Check Copper Fern Lab and the three invented equipment names against the page images.
  • Keep each asset ID attached to its own record: LAB-101, LAB-204 and LAB-308.
  • Check quantities 2, 3 and 4, the printed total 9, shelf codes, dates and the session time.
  • Read the complete text as well as the field report. A field tally alone cannot show every possible error.

A checker exit of 1 means the text needs review. It does not mean the OCR command failed to create a PDF. A checker exit of 0 means a full match under this exercise’s comparison rules; 2 means an input, package or report error. Your OCR version may produce different results. Record zero corrections if your actual output matches; do not invent this example’s mistake.

5. Save a reviewed text copy

Keep the raw PDF and text. Copy the text to a new file before making a correction:

cp my-run/ocr.txt my-run/reviewed-text.txt

Open the new file in a plain-text editor. Compare every reported difference with the page image and answer key. In the observed example, remove only the extra O from the page-one document ID. Do not apply a blanket O-to-zero replacement. Then run:

python3 validate.py my-run/reviewed-text.txt \
  --report my-run/reviewed-validation.json

The supplied output/reviewed-text.txt contains that single verified correction and passes all 34 field checks plus the full-text comparison. Correcting a text file does not correct the PDF’s hidden text layer. The supplied raw searchable PDF still contains the known ID error. Use the reviewed text when you need the checked transcription.

If something goes wrong

  • A prerequisite is missing: stop and consult the official setup links. There is no blanket privileged install command in this exercise.
  • The output folder exists: choose a new run name and preserve the previous attempt.
  • The input already has text: use input/scanned-inventory.pdf, not the source master or an OCR output.
  • A number or identifier is wrong: inspect the scan, retain the raw output and edit a reviewed text copy.
  • Spacing is visibly broken before OCR: fix the source or scan first. During preparation, embedding the source font resolved a rendering problem before the final input was selected. That preparation issue is separate from the final OCR mistake.

What this exercise covers

Keep the input, raw result, reviewed text and version record together so you can explain what was checked. The included evidence verifies the image-only input, unchanged page appearance after OCR and the observed identifier error. No recognition errors were added by hand.

Coverage is limited to two clean, single-column English pages. Handwriting, poor photographs, damaged pages, complex tables, rotation, other languages and sensitive-document handling were not tested. The ordinary searchable PDF is untagged; no PDF/A or accessibility conformance is claimed. Processing used command-line tools without an OCR web API, but this was not a privacy audit. The results support no hardware-performance or overall OCR-accuracy conclusion.

Next step

The sidecar contains text from pages OCRmyPDF actually processed, not necessarily every page in an arbitrary PDF. Existing text pages or pages skipped by processing limits can be absent. This exercise uses two image-only pages; for another document, compare the page count and extract the final PDF’s text as well. OCRmyPDF explains the sidecar limitation.

Once you have checked the transcription, try the fictional invoice extraction exercise to practice turning plain text into structured data. It is a separate exercise, not a tested end-to-end OCR-to-invoice pipeline. For hardware decisions, use the workload test record rather than inferring speed from this small OCR sample.

For new reporting, add our RSS feed to your reader. Browse Guides & Tools for the full practice sequence. The feed does not announce every guide revision.

Take it back to the community

Tried this on your setup? Share what worked and what did not, with enough detail for someone else to repeat it. Still stuck? Start with three lines. Experienced readers can check a step and suggest a correction.

Find the weekly workshop, then return to your original thread with the outcome. A helpful contribution earns thanks, not an automatic evidence label.