Disabling Tesseract's dictionary changed nothing. A word list did.
0
lines changed of 3,600, dictionaries off
For printed scans: $0.006 a page
The off switch changes nothing
The docs say it helps on text that is not dictionary words.
| Text, 300 lines each | Words right | Lines changed |
|---|---|---|
| Book prose | 2,446 of 2,451 | 0 |
| Part codes, emails, names | 911 of 1,006 | 0 |
| Invoice lines | 1,680 of 1,686 | 0 |
Codes like T0WN |
527 of 803 | 0 |
On 72 full invoice pages, 0 of 7,609 words changed.
How I tested it
-
Tesseract 5.5.4, the Homebrew eng model, the LSTM engine, one line
at a time at
--psm 7. - 1,200 made-up lines: prose from Pride and Prejudice, part codes, invoice rows, and words with a digit swapped in.
- Times New Roman at 26 px, with tilt, blur, noise and JPEG, like a scan.
- Tesseract's parameter dump showed both flags set to 0.
- I ran it again at 21 px, and with tessdata_best. Dictionaries off changed 0 lines both times.
-
A word is right when it matches the truth exactly, case and
punctuation included. Full pages: my 72 test invoices, at
--psm 3.
A list of your codes helps
--user-words takes a file with one word per line.
--user-patterns takes shapes, such as
\A\A-\d\d\d\d\A for two capitals, a dash, four digits and
a capital.
tesseract line.png - --psm 7 -c load_system_dawg=0 -c load_freq_dawg=0
tesseract line.png - --psm 7 --user-words parts.txt
tesseract line.png - --psm 7 --user-patterns patterns.txt
The list held the 577 codes and names on the lines, plus 1,925 made-up decoys. Neither option broke a word that was right.
In Python, one config string
pytesseract hands the config string to the tesseract command, so both flags go in one string:
import pytesseract
from PIL import Image
img = Image.open("line.png")
off = pytesseract.image_to_string(img, config="--psm 7 -c load_system_dawg=0 -c load_freq_dawg=0")
words = pytesseract.image_to_string(img, config="--psm 7 --user-words parts.txt")
For 0 and O, fix it after OCR
Tesseract read the digit 0 as the letter O, and 1 as I, inside words. The dictionary flags did not change that.
-
Part 100-H01X qty 37: Tesseract readHO1X. Snap fixed it. -
Bin T0WN D1LATORY: Tesseract readTOWN DILATORY. Snap fixedT0WNand leftDILATORY, because two list words fit it.
Codes like T0WN |
Words right, of 803 |
|---|---|
| Default | 527 |
| --user-words | 540 |
| Snap after OCR | 650 |
snap(), in 17 lines of Python
It swaps a word for the one list word it can be confused with. Give it
the same list you would give --user-words.
# each lookalike group maps to one character
LOOK = str.maketrans("O0Il1S5B8Z2", "00111558822")
def snap(text, known):
"""Swap each word for the one known word it looks like, if exactly one fits."""
by_key = {}
for w in known:
by_key.setdefault(w.translate(LOOK), set()).add(w)
out = []
for word in text.split():
core = word.strip(",.;:")
match = by_key.get(core.translate(LOOK), set())
out.append(
word.replace(core, next(iter(match)))
if core not in known and len(match) == 1
else word
)
return " ".join(out)
Limits, and what I did not test
- Real scans. Every line here is made up, in one font.
-
The legacy engine,
--oem 0. The Homebrew model has no legacy data. - Missing codes. The lists held every code on the test lines, and a real parts list can miss some. Snap leaves those alone.
Sources
Our Actor leaves the dictionaries alone
Our Apify Actor takes no word list or patterns, and keeps Tesseract's dictionary settings as shipped. When it reads a table number a second time, it allows only digits and separators.
Two ways to skip the work
Run it yourself. Our Apify Actor turns scanned PDFs into Markdown, tables included.
Or send us the scan. Tack, our AI, does the job for $29, up to 50 pages. First page free.
Questions people ask
How do I disable the dictionary in pytesseract?
Pass config="-c load_system_dawg=0 -c load_freq_dawg=0", both flags in one string. On Tesseract 5.5.4 it changed 0 of 3,600 test lines.
Does --user-words work with the LSTM engine?
Yes, on Tesseract 5.5.4. A list of part codes raised code words read right from 911 to 965 of 1,006, and broke none.
Can Tesseract read only the words in my list?
No. The list only nudges. With the parts list on, the 300 book lines came out as before, though only 3 of their 916 different words were on it.