PDF 的 Tesseract OCR
与可搜索 PDF。
用 Tesseract 对 PDF 做 OCR 的完整、经过验证的指南:栅格化页面、创建可搜索 PDF、使用 OCRmyPDF 和 pdfsandwich、在 Python 中端到端运行,并解决常见错误。
摘要(一条命令)
对于真实的多页 PDF,OCRmyPDF 是最快的路径。
pip install ocrmypdf # 或:apt install ocrmypdf
ocrmypdf input.pdf output.pdf没有 OCRmyPDF?栅格化后直接使用 Tesseract CLI —— 见下文。
为什么 PDF 必须栅格化
Tesseract 识别图片,而不是 PDF 容器。
PDF 是容器:可能包含矢量文字、嵌入字体或扫描的页面图片。Tesseract 读取栅格图片(TIFF、PNG、JPEG、WebP 等),因此必须先把页面转换为图片。根据已安装的工具选择栅格化器:
| 工具 | 安装 | 备注 |
|---|---|---|
pdftoppm(poppler) | apt install poppler-utils | 快速、可脚本化,经典选择 |
pdftocairo(poppler) | poppler-utils | 与 pdftoppm 类似,Cairo 输出 |
| ImageMagick | apt install imagemagick | convert -density 300 in.pdf out.tif |
| PyMuPDF | pip install pymupdf | 纯 Python,无需外部二进制 |
| pdf2image | pip install pdf2image | 封装 poppler 的 Python 库 |
# PDF -> 每页一个 300 DPI 的 PNG
pdftoppm -png -r 300 input.pdf pageDPI 最重要:300 DPI 是标准平衡;小字体或归档用 600 DPI;避免低于 200 DPI。
用 Tesseract CLI 创建可搜索 PDF
使用 pdf 输出配置,一张图片就成为一页可搜索 PDF。
# 图片 -> 可搜索 PDF
tesseract page-1.png output pdf
# 仅文字层(不显示图片)
tesseract scan.png output textonly_pdf
# 多页合成一个 PDF:传入图片列表
tesseract imagelist.txt output pdf多页 PDF 时,把每个图片路径写在一行放入 imagelist.txt。完整输出格式参考:文档。
方法 B — OCRmyPDF(真实 PDF 推荐)
OCRmyPDF 用一条命令完成栅格化、OCR、纠偏、旋转和不可见文字层。
ocrmypdf input.pdf output.pdf # 基础
ocrmypdf -l eng+chi_sim input.pdf output.pdf # 语言
ocrmypdf --deskew --rotate-pages input.pdf output.pdf
ocrmypdf --optimize 2 input.pdf output.pdf # 缩小文件
ocrmypdf --skip-text input.pdf output.pdf # 保留已有文字的页面OCRmyPDF 内部使用 Tesseract,需要 Ghostscript 和 poppler 工具。常用选项:--force-ocr、--redo-ocr、--pages 1-10。
方法 C — pdfsandwich
更轻量的封装,添加文字层并执行纠偏等预处理。
pdfsandwich scan.pdf # 生成 scan_ocr.pdf
pdfsandwich -lang eng+chi_sim scan.pdf方法 D — Python 端到端
用 pdf2image 栅格化,用 pytesseract 构建可搜索 PDF,再用 pypdf 合并。
import io, pytesseract
from pdf2image import convert_from_path
from pypdf import PdfWriter, PdfReader
pages = convert_from_path("input.pdf", dpi=300) # 需要 poppler
writer = PdfWriter()
for page in pages:
pdf_bytes = pytesseract.image_to_pdf_or_hocr(page, extension="pdf", lang="chi_sim")
writer.add_page(PdfReader(io.BytesIO(pdf_bytes)).pages[0])
with open("output.pdf", "wb") as f:
writer.write(f)在 Windows 上,通过 poppler_path= 传入 poppler 的 bin 文件夹。更多细节见 pytesseract 指南。
该用哪种方法?
| 方法 | 适合 | 配置 | 多页 |
|---|---|---|---|
| OCRmyPDF | 真实 PDF、自动化 | Ghostscript + poppler | 一条命令即可 |
| pdfsandwich | 带预处理的快速文字层 | poppler + ImageMagick | 是 |
| Tesseract CLI | 图片或图片列表 | 仅需 Tesseract | 通过图片列表 |
| Python(pdf2image) | 流水线与自定义逻辑 | poppler + pytesseract | 循环并合并 |
版面保真与文字叠加
可搜索 PDF 有时看起来错位的原因,以及如何保持几何精度。
- 不可见文字层根据 OCR 的单词框放置;DPI 错误时叠加会偏移。
- 需要精确坐标(高亮或归档)时使用
hOCR或ALTO输出。 pdftoppm -r 300并匹配原始页面尺寸可保持叠加对齐。- 复杂版面优先使用 OCRmyPDF,它保留原始图像并在原位添加文字层。
质量与性能
- DPI:300 为标准,小字体或归档用 600。
- 页面范围:只处理需要的部分(OCRmyPDF 的
--pages)。 - 并行:并行对各页做 OCR 再合并。
- 体积:使用
--optimize/ JPEG 压缩,或在 OCR 后降低 DPI。 - 预处理:OCR 前先纠偏和去噪。
故障排查
| 症状 | 原因 | 解决方法 |
|---|---|---|
Unable to get page count. Is poppler installed? | pdf2image 找不到 poppler | 安装 poppler-utils,或在 Windows 上设置 poppler_path。 |
| 输出 PDF 没有可搜索文字 | OCR 未运行或语言错误 | 确认成功,并把 -l/--language 设为文档语言。 |
| 文字叠加错位 | DPI 或页面尺寸错误 | 以原始尺寸按 300 DPI 栅格化。 |
| 输出文件巨大 | 600 DPI 无损图片 | 使用 --optimize / JPEG,或降低 DPI。 |
| 受密码保护的 PDF 失败 | 加密输入 | 先解密,或传入工具支持的密码参数。 |
PDF 常见问题
如何让 PDF 可搜索?
使用 ocrmypdf input.pdf output.pdf,或栅格化页面后运行 tesseract page.tif output pdf。
为什么 Tesseract 不能直接读取 PDF?
Tesseract 识别栅格图片,因此必须先转换 PDF 页面。
该用多少 DPI?
大多数文档用 300 DPI;小字体或归档用 600 DPI。
能在 Python 中对 PDF 做 OCR 吗?
可以 —— 用 pdf2image 配合 poppler 和 pytesseract.image_to_pdf_or_hocr,再用 pypdf 合并页面。
如何保持版面精确?
保持原始页面尺寸和 DPI,并优先使用 OCRmyPDF,它保留图像并叠加文字层。