Tools,

Tesseract and two columns: the default reads them right

99%

of the text in order with psm 3

Get the code

psm 4 and 6 read straight across

Proofread two-column scans from 4 encyclopedias, printed 1879 to 1921:

Setting In order Words found
--psm 3, the default 99.2% 95.8%
--psm 4 56.2% 93.9%
--psm 6 50.8% 92.6%

30 of 30 pages 90% or more in order at psm 3

0 of 30 at psm 6

psm 4 and 6 skip the column search, so each line runs across both columns:

Setting First line read
psm 6 he had to fly for his life in the disguise of a priest. In the next | ecclesiastical. This double character is sufficient to explain
psm 3 he had to fly for his life in the disguise of a priest. In the next

Sorting word boxes by row breaks it too

A common recipe takes the word boxes from image_to_data and sorts them into rows by height. Lines of both columns sit at the same height, so they merge.

51.1% in order, boxes sorted into rows

99.2% in Tesseract's own order

Row sorting suits one-column receipts, as in our receipt guide. Not columns.

Keep the default and Tesseract's order

Leave out --psm. This writes page.txt with psm 3:

tesseract page.png page

In Python, if you need the word boxes, group them by block, paragraph and line, in the order Tesseract gives them:

import pytesseract
from pytesseract import Output

d = pytesseract.image_to_data("page.png", output_type=Output.DICT)
lines = {}
for i, word in enumerate(d["text"]):
    if word.strip():
        key = (d["block_num"][i], d["par_num"][i], d["line_num"][i])
        lines.setdefault(key, []).append(word)
text = "\n".join(" ".join(words) for words in lines.values())
print(text)

Cutting the page in half adds little

I also cut each page at the whitest strip near its middle and read each half. That kept 99.3% in order, against 99.2% for the whole page.

How I tested it
  • Pages: en.wikisource scans whose text was proofread (level 3) or also checked by a second person (level 4). Picked by a seeded shuffle, not by me. Pages with tables, pictures or math were skipped.
  • Encyclopaedia Britannica, 1911: 16 pages
  • New International Encyclopaedia, 1st ed.: 9 pages
  • American Cyclopaedia, 1879: 3 pages
  • Collier's New Encyclopedia, 1921: 2 pages
  • Each scan is the wiki's page image, 1,280 px or 1,920 px wide.
  • Running heads, page numbers and footnotes are not in the proofread text, so extra text costs nothing.
  • In order: proofread letters and digits found in the same order. Words found: proofread words found anywhere on the page.
  • --psm 1 read the same as psm 3 on all 30 pages.
  • Tesseract 5.5.4 with the eng file Homebrew installs (tessdata_fast 4.1.0), one thread.

Our Actor reads them in order

Our Apify Actor does its own layout step after Tesseract. On these 30 scans:

99.2% in order, live build 0.1.65

50.7% in order, old build 0.1.44

Build 0.1.65, live since Nov 11, splits narrow columns first. It matches psm 3: 99.2%. Each number is a build's code, run on my Mac.

What I did not test
  • Three or more columns, newspapers and magazines.
  • Pages that mix columns with tables or pictures.
  • Phone photos of curved book pages.
  • Languages other than English. Hindi two-column pages are on this page.
  • Windows and Linux. One Mac.
Sources

Two ways to skip the work

Run it yourself. Our Apify Actor turns scanned PDFs into Markdown, tables included.

Try the Actor

Or send us the scan. Tack, our AI, does the job for $29, up to 50 pages. First page free.

Get one page free

Questions people ask

Can Tesseract read two columns?

Yes, at its default psm 3. On 30 proofread scans it kept 99.2% of the text in order. psm 4 and 6 read across the columns.

Why does Tesseract mix up my columns?

Usually psm 4 or 6, or code that sorts the word boxes into rows. Each kept about half the text in order on 30 scans.

Do I need to split columns before OCR?

Not on clean scans like these. Cutting each page at its gutter kept 99.3% in order, against 99.2% for psm 3 on the whole page.