Towards Data Science

Parse Scanned PDFs for RAG with EasyOCR: Free OCR Gives You Words, Not a Document

8.5内容质量

TL;DR · AI 摘要

EasyOCR 仅能提取文本,无法解析文档结构,而 Docling 可提取文本、段落、图表等结构信息,更适合 RAG 系统。

核心要点

  • EasyOCR 仅能提取文本,无法解析文档结构。
  • Docling 可提取文本、段落、图表等结构信息。
  • 传统 OCR 无法满足企业级 RAG 系统对文档结构的需求。

结构提纲

按章节快速跳转。

  1. 本文介绍如何使用 EasyOCR 解析扫描 PDF,但指出其局限性。

  2. 传统 OCR 仅能提取文本,无法解析文档结构。

  3. EasyOCR 是一个免费的 OCR 工具,仅能提取文本。

  4. Docling 的功能

    Docling 是一个布局感知的解析引擎,可提取文本、段落、图表等结构信息。

  5. EasyOCR 和 Docling 在解析扫描 PDF 时的表现对比。

  6. 使用 1974 年的扫描 PDF 作为案例,对比两种解析引擎的输出。

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • 解析扫描 PDF 的挑战
    • 传统 OCR 的局限性
      • 仅提取文本
      • 无法解析文档结构
    • Docling 的优势
      • 提取文本、段落、图表
      • 适合 RAG 系统

金句 / Highlights

值得收藏与分享的关键句。

  • Traditional OCR gives you the text. It gives you nothing else. The rest is the layout problem, and the layout problem is the harder half.

    第 3 段

    ⬇︎ 下载 PNG𝕏 分享到 X
  • EasyOCR is the OCR floor: line_df only, no layout. The rest of the family adds structure.

    第 5 段

    ⬇︎ 下载 PNG𝕏 分享到 X
  • The whole article is a setup for the head-to-head on a real public-domain 1974 scan in section 5.

    第 4 段

    ⬇︎ 下载 PNG𝕏 分享到 X
#EasyOCR#Docling#RAG#OCR#PDF解析
打开原文

使用 EasyOCR 解析扫描的 PDF 以实现 RAG:免费 OCR 提供文字,而非文档 | Towards Data Science

大型语言模型

使用 EasyOCR 解析扫描的 PDF 以实现 RAG:免费 OCR 提供文字,而非文档

企业文档智能 [Vol.1 #5quinquies] – 同样的 1974 年扫描 PDF,两个引擎。EasyOCR 恢复文本。Docling 恢复文本 + 章节 + 图表。结构上的差距使一个输出可以用于下游,而另一个则只是一个扁平字符串。

Kezhan Shi

2026 年 6 月 19 日

15 分钟阅读

分享

照片由 Aakash Chary 提供,来源:Pexels。

本文是《企业文档智能》系列文章的解析指南,该系列文章通过四个模块构建企业 RAG 系统。第 5 篇(文档解析)使用 PyMuPDF(fitz)构建了解析器,当扫描的页面没有文本层时,该解析器返回空值。本指南则将引擎替换为 EasyOCR,这是一个免费的 OCR 包,可以恢复文本。这是该系列中唯一一个新引擎提供更少信息的情况,而非更多:它只恢复文本,而没有其他内容,这种差距就是教训。

本指南的位置:它扩展了第 5 篇(文档解析),在第 II 部分(四个模块)中,使用不同的解析引擎 – 图片由作者提供

扫描的 PDF 并不能通过“仅仅使用 OCR”来解决。OCR 步骤可以恢复文本,这是必要的,但不足以构建企业 RAG 管道。管道还需要文本周围的其他信息:页面边界在哪里,哪些行是章节标题,什么是图表,什么是表格行与自由段落。传统的 OCR(用于文本检测 + 文本识别引擎的术语,如 EasyOCR、TesseractPaddleOCR)只提供文本。它不提供其他任何信息。其余部分是布局问题,而布局问题是更难的一半。

本文具体地展示了这一区别。传统的 OCR 引擎是 EasyOCR:最简单、最快、免费的 JaidedAI 文本检测 + 识别库(Apache 2.0,声明在项目 LICENSE 文件中)。布局感知引擎是 Docling(第 5ter 篇;MIT 许可,声明在项目 LICENSE 文件中)。两者都可以对扫描页面进行 OCR。它们的区别在于如何处理结果。整篇文章为第 5 篇中对一个真实公共领域 1974 年扫描的正面交锋做铺垫。

EasyOCR 是 OCR 的基础:只有 line_df,没有布局。其余的模块添加了结构 – 图片由作者提供

1. 传统 OCR 的作用(以及不作用的地方)

传统 OCR 读取像素并返回文本矩形。其他所有内容,如章节、表格、图表、阅读顺序,都是引擎拒绝处理的布局问题。其背后的两个模型是文本检测(找到图像中包含文本的矩形区域)和文本识别(读取每个区域的像素并返回带有置信度的字符)。输出是每个检测区域的扁平列表,包含(边界框,文本,置信度)。

这就是 EasyOCR(或 Tesseract、或 PaddleOCR)所做的一切。引擎读取像素并返回文本矩形。一个双栏页面返回为一个由 y 坐标交错的左和右文本框的扁平列表;引擎不知道有两栏。一个表格返回为一个无法区分普通段落的断开单元格网格。一个图表标题只是一个文本框。页面标题、页面页脚、页边注释都会显示为框。

任何需要“这段文字是小节标题”或“这四个框是一个表格行”的内容都需要在基础模型之上增加一个布局模型。布局模型会读取OCR输出结果和页面图像,并对每个区域(标题、段落、表格单元格、图表、图注、页脚等)进行分类,并将其按阅读顺序进行分组。这就是Article 5bis(Azure DI)、Article 5ter(Docling)和Article 5quater(vision LLM)在OCR步骤基础上所添加的内容。如果没有布局模型,你得到的只是“OCR输出”,而不是“解析后的文档”。

2. EasyOCR:传统的OCR典范

EasyOCR是对“传统OCR”这一类别最清晰的演示。该库体积小(首次调用时缓存约150 MB的模型权重),免费,默认仅使用CPU,本地运行。整个库的API只有两个调用:为所需语言构建一个Reader,然后将图像传递给readtext。每个检测结果返回一个三元组:文本周围的多边形、识别出的字符串以及识别器自身的置信度。

code
import easyocr
import fitz
import numpy as np

reader = easyocr.Reader(["en"], gpu=False)        # 首次调用时下载约150 MB

# 将扫描的PDF第一页渲染为EasyOCR可读的numpy数组
page = fitz.open("data/contracts/scanned_amendment.pdf")[0]
pix = page.get_pixmap(matrix=fitz.Matrix(2.0, 2.0))   # 2倍缩放 = 约144 DPI
img = np.frombuffer(pix.samples, dtype=np.uint8).reshape(
    pix.height, pix.width, pix.n,
)

# 识别器:输入一张图像,输出每个检测到的文本区域的三元组
detections = reader.readtext(img)
for quad, text, conf in detections:
    # quad = [[x0,y0], [x1,y0], [x1,y1], [x0,y1]] 以像素坐标表示
    print(round(conf, 2), text)

parse_pdf_easyocr封装了这个循环。它遍历PDF的每一页,将每一页渲染为numpy数组,调用readtext,将像素空间中的多边形转换回PDF坐标,并将检测结果打包到与其它解析器相同的表格字典中,相同的line_df,相同的parsing_summary,相同的下游消费者,只是只有那两个键包含数据。其他所有插槽(page_df、image_df、toc_df、span_df、object_registry、cross_ref_df)都返回空的DataFrame。这不是一个缺失功能的错误;这正是“传统OCR”所指的含义。

code
parsed = parse_pdf_easyocr(
    "data/contracts/scanned_amendment.pdf",
    languages=("en",),         # 添加"fr"、"de"等以支持多语言扫描
    render_scale=2.0,          # 2.0 = 约144 DPI;字体较小时可提高
    gpu=False,                 # 默认仅使用CPU;如果可用CUDA,可设为True
    confidence_threshold=0.0,  # 如需过滤低置信度的检测,可设置阈值
)

parsed["line_df"]              # 每个检测的文本 + 边界框 + 置信度
parsed["parsing_summary"]      # 方法、页数、行数、渲染比例
# 所有其他键(page_df、image_df、toc_df、span_df、object_registry、
# cross_ref_df)都是空的DataFrame;EasyOCR在这些位置没有内容可填。

签名的kwargs是唯一的调节参数:

  • languages:ISO-639-1代码的元组(如en、fr、de、zh等)。一个包含多种语言的语料库会为每种语言加载一个Reader;get_easyocr_reader中的@lru_cache会在多次调用之间缓存几个这样的Reader。
  • render_scale:在将每一页栅格化时,每PDF单位的像素数。1.0是原生的(约72 DPI,通常太小)。2.0是正文文本的理想值。字体非常小时可提高到3.0;如果内存受限,可降低。
  • gpu:默认使用CPU,因此该模块可以在任何机器上运行。CUDA在文本密集的页面上可提供3-5倍的速度提升。
  • confidence_threshold : 过滤掉低置信度的检测结果。0.0 保留所有内容(该列被保留下来以便后续代码进行过滤),0.3 可以在降质扫描中去除大部分噪声。

3. line_df 的结构

来自 NIST FIPS 199 封面的示例行(美国政府作品,在美国属于公共领域,详见 NIST 版权声明),每行对应一个检测到的文本区域:页面坐标、OCR 识别的文本以及识别器自身的置信度评分。这就是全部的输出。

与 fitz 的 line_df 具有相同的列结构,再加上 EasyOCR 自动添加的一列置信度 – 图片由作者创作

结构特意保持简洁:

  • text + bbox : 识别器的输出内容,每行对应一个检测到的文本区域。
  • confidence : 0 到 1 之间的浮点数,EasyOCR 的自我评分。既可以作为过滤器(在噪声扫描中丢弃低于 0.3 的内容),也可以作为反馈信号(文章 8 的生成可以将低置信度段落标记给用户)。
  • character_count : 为了与其他解析器对称而保留;在 EasyOCR 中,它只是 len(text) 的值。
  • 无列 / 阅读顺序列。一个双列页面返回为一个扁平列表,左右框根据 y 坐标混合排列。

返回字典(page_df、image_df、toc_df、span_df、object_registry、cross_ref_df)中的其他所有键都是空的 DataFrame。调用 parsed["image_df"] 的消费者不会崩溃;它会遍历一个空的框架。

4. 传统 OCR 无法识别的结构缺陷,逐项说明

RAG 管道需要的五个结构性特征,无论识别模型有多大,传统 OCR 都无法生成。每一个都会破坏整个系列依赖的下游操作。

  • 目录 / 章节。交叉引用解析(文章 11)和章节范围内的语料库检索(文章 17)都依赖于 toc_df。EasyOCR 返回零行。调度器无法处理“在第 3.2 节中回答”的问题,因为第 3.2 节没有边界。
  • 页面内的单个图表。一份 30 页的扫描合同可能包含嵌入在正文中的六张图表截图。EasyOCR 将整个页面视为一张图像,返回图表周围的文本;图表本身从未成为行。需要检索“第 14 页的图表”的下游管道没有可操作的引用。
  • 多列或多区域页面的阅读顺序。一个双列的科学论文页面返回为从上到下跨两列混合排列:左行 1、右行 1、左行 2、右行 2……生成内容会读取垃圾信息。边栏、脚注、页边注释都会泄漏到主流程中。
  • 表格单元格。扫描的费用表或保费表返回为一个不连贯文本框的扁平列表(行标签在一个列中,值在另一个列中,单位标题在其他地方)。这种“该值属于该标签”的关系丢失。文章 5(文档解析)正是从这种失败模式开始(“解析器逐单元格遍历表格并将其连接成一个扁平字符串”)。布局感知引擎运行一个独立的 TableFormer 风格模型以重建行 × 列 × 标题。
  • 字体 / 粗细 / 大小信号。OCR 恢复字符形状,而不是其排版编码。“此行是粗体 18pt”是布局引擎从页面渲染中读取的信息;EasyOCR 丢弃了这些信息。标题、强调、脚注失去了用于分类的提示。

选择第三个因素,即阅读顺序,因为它会悄无声息地破坏答案。EasyOCR 按照文本框的 y 坐标对它们进行排序。在双栏页面上,两栏位于相同的高度,因此文本框会交错返回:左栏的第一行、右栏的第一行、左栏的第二行,依此类推。文本以锯齿状方式阅读,生成的引文也呈锯齿状。

没有布局模型时,文本框按照 y 坐标排序,因此双栏页面会交错成锯齿状 – 图片由作者提供

一句话:OCR 步骤恢复文本,布局步骤恢复使文本可用的结构。第 5ter 篇(Docling)和第 5bis 篇(Azure DI)在相同的 OCR 基础上增加了布局步骤。第 5quater 篇(视觉 LLM)将两者合并为一次调用。EasyOCR 仅停留在 OCR 步骤。

5. EasyOCR 与 Docling 在真实扫描 PDF 上的对比

在相同的 1974 年扫描文件上,Docling 提取了更多的字符(5,423 个 vs 4,952 个),页面边界、11 个目录条目和 4 个图像区域。EasyOCR 提取文本矩形并停止。这两个引擎在字符级别上达成一致,都使用相同识别器类别的准确率进行 OCR,但 Docling 的布局步骤将 OCR 输出转换为文档。

有趣的是,这次比较不是与 fitz(fitz 在扫描上返回零)进行,而是与下一个引擎进行比较:Docling,来自第 5ter 篇的本地布局感知解析器。比较看起来比实际更清晰:Docling 的默认 OCR 后端本身就是 EasyOCR。相同的识别器读取相同的像素;差异在于 Docling 围绕它构建的一切。

测试用例是一个真实的公共领域扫描文件:karg74.pdf 的第 1–5 页,1974 年美国空军 MULTICS 安全评估(Karger & Schell,ESD-TR-74-193 第 II 卷)。NIST 在他们的早期计算机安全论文档案中托管了该文件;该作品作为美国空军军官的成果,已进入公共领域。该 PDF 内置了 Adobe 的“Paper Capture”OCR 层,但我们忽略了它,两个引擎都从页面图像重新进行 OCR,这是嵌入的 OCR(如果存在)不可靠时的现实场景。

真正的比较。两个引擎都对页面图像重新进行 OCR;Docling 添加了布局 – 图片由作者提供

两栏讲述了不同的故事。

EasyOCR(左)。更快(59.7 秒 vs 134.4 秒,没有布局模型需要加载和运行),将识别器的置信度作为一列输出(在这次扫描中平均为 0.81),产生更多的行级检测(346 个框),因为页面上的每个文本区域都变成一行。没有结构:没有 page_df、没有 toc_df、没有 image_df。输出是文本框形式的文本,仅此而已。

Docling(右)。更慢(计算量是前者的 2.3 倍),将检测结果合并为 105 行/段落,而不是 346 个框,没有置信度列。结构上的优势是真实的:5 行 page_df、11 个 toc_df 条目(Docling 的布局模型将标题分类为章节)、4 行 image_df(在页面内检测到的图像作为独立对象)。在包含表格的 PDF 上,差距进一步扩大,Docling 的 TableFormer 可以识别行 × 列 × 标题,而 EasyOCR 完全无法做到。第 5ter 篇详细介绍了表格情况。

在这次 1974 年的扫描(Karger → “Karger” 由 EasyOCR,干净页面上 “Karger” 由 Docling)上,两个引擎在字符级别的错误率相似(退化区域在两者上产生相似的噪声,“Laboralory”,“und” 而不是 “and”)。Docling 内部的 OCR 引擎(根据安装情况为 EasyOCR 或 OnnxTR)并不比直接调用 EasyOCR 更神奇地准确。Docling 增加的是它如何组织 OCR 输出,而不是如何进行 OCR。

在企业级 RAG 应用中,选择 Docling 通常是正确的决定。2.3 倍的计算开销只需在摄入阶段支付一次(来自第 5 篇文章(文档解析)的解析缓存会永久复用结果);而结构化收益(目录、图表、表格单元格、阅读顺序)则会在每次下游查询中得到回报。Docling 唯一不提供的是 EasyOCR 的行级置信度信号,这种信号在大多数情况下都不值得牺牲文档的段落、图表和表格。

6. 传统 OCR 依然有其价值的场景

EasyOCR 是这个系列中的应急方案:对文档的可见性较低,依赖项更简单,当限制是操作性而非教学性时,部署速度更快。有四种特定场景仍然为 EasyOCR 保留了空间。

  • 收据类文档。一页的发票或收据,没有标题、没有段落、没有图表、没有合并单元格的表格。布局非常简单;识别器就是整个任务。添加 Docling 的 2 倍计算开销,只是为了获得文档本身没有的结构。
  • 按区域置信度作为生成反馈信号。生成(第 8 篇文章)可以从引用段落中读取行的置信度,并在答案依赖于 OCR 置信度为 0.3 的部分时提醒用户。Docling 不提供该列。对于依赖该信号的流水线,EasyOCR(或与 Docling 一起运行 EasyOCR)是答案。
  • 大规模非拉丁文脚本。EasyOCR 提供了 80 多种语言的预训练模型,包括中文、日文、韩文、阿拉伯文、印地文、西里尔文。在撰写本文时,Docling 的 OCR 堆栈在非拉丁文覆盖范围上更为有限。
  • 操作限制阻止使用 Docling。公司 SSL 检查会破坏 HuggingFace 模型下载。Windows 在没有开发人员模式的情况下会阻止符号链接。生产镜像有严格的依赖预算。无法传输 3GB 布局权重的隔离部署。在所有这些情况下,EasyOCR 的 150MB 缓存模型 + CPU 推理都能通过,而 Docling 则无法通过。你看到的文档内容更少,但你至少能看到一些内容。

在这些情况之外:默认使用 Docling 进行扫描,Azure DI 用于合规云环境,当文档包含手写体、签名或非文本语义层时使用视觉 LLM。第 10 篇文章中的自适应解析调度器会自动进行路由。

7. 结论

OCR 恢复字符。布局恢复的是使字符有用的部分,包括段落、图表、表格单元格和阅读顺序。扫描的默认引擎是能同时完成这两项任务的引擎。第 5 篇文章中的完整家族也按照同样的轴线排列:

EasyOCR 位于 OCR 基础层(仅 line_df);家族中的其他引擎则在 OCR 之上增加了一个布局步骤 – 图片由作者提供

EasyOCR 是 OCR 的基础层,当你只停留在识别字符,而从未问过“它们在页面上的位置”时,你得到的就是 EasyOCR。这个问题很重要。“在页面上的位置”决定了你得到的是文本框列表还是解析后的文档。第 10 篇文章中的调度器(自适应解析)会根据每一页选择合适的引擎;本文的存在是为了让调度器知道,当它选择便宜的引擎时,它放弃了什么。

8. 参考资料和进一步阅读

EasyOCR 是 2026 年最易获取的传统 OCR 引擎;PaddleOCR(百度)和 Tesseract(Google,已有数十年历史)与它同属一个家族。顶部的布局步骤是区分“OCR”与“文档解析”的关键;Docling(第 5ter 篇文章)和 Azure DI(第 5bis 篇文章)分别在本地硬件和云端添加了这一功能。右侧的横向阅读涉及布局文献(Smock 等人,2022 年关于表格结构;Auer 等人,2024 年关于完整布局级联)以及适用于非拉丁语脚本的替代 OCR 引擎。

与文章方向一致:

  • JaidedAI, EasyOCR。本文所描述的库,包括 80 多种语言模型包。
  • PaddleOCR(百度)。同级别的传统 OCR 引擎;中文覆盖率更好,但同样存在布局盲区。
  • Tesseract OCR。已有数十年历史的经典工具,仍被广泛部署;与 EasyOCR 相同的架构设计(检测 + 识别,无布局处理)。

不同角度,不同背景:

  • Auer 等人,Docling 技术报告,IBM 研究 2024 年(arXiv:2408.09869)。一个布局感知的级联系统,将 OCR 输出转换为解析后的文档;本文第 5 节的比较基准。
  • Smock、Pesala、Abraham,PubTables-1M / Table Transformer(TATR),CVPR 2022 年(arXiv:2110.00061)。单元格级表格提取的研究背景,也是 EasyOCR 最大的缺失能力。

系列文章的早期内容:

  • 文档智能:系列简介。系列逐步构建的内容及顺序。
  • 基线企业 RAG,从 PDF 到高亮答案。一个四步骤的完整流程:输入 PDF,输出高亮答案。
  • 嵌入向量并非魔法:RAG 检索的可预测失败模式。嵌入相似性在哪些情况下有效(同义词、拼写错误、改写),在哪些情况下会可预测地失效(未知术语、否定、术语与答案的相关性),以及如何使用它。
  • 重排序器也并非魔法:何时使用交叉编码器层值得付出代价。交叉编码器相对于双编码器嵌入向量的额外优势,以及何时值得承担延迟成本。
  • RAG 并不是机器学习,而机器学习工具箱解决的是错误的问题。为什么块大小调整和微调优化的是错误的目标;应根据问题类型进行路由。
  • 从正则表达式到视觉模型:哪种 RAG 技术适合哪种问题。两个维度,文档复杂性和问题控制,用于选择每种情况下的技术。
  • 我们在生产中反复看到的 10 个常见 RAG 错误。10 个生产错误,按步骤组织,并附有每个错误的修复方法。
  • 超越 extract_text:驱动 RAG 质量的 PDF 的两个层次。解析步骤的第一部分:文档的性质、信号和摘要。
  • 停止从 PDF 返回扁平文本:RAG 所需的关系结构。解析步骤的第二部分:每个下游步骤都会读取的关系表。

撰写者

查看 Kezhan Shi 的所有文章

文档处理

,

OCR

解析

PDF

RAG

分享这篇文章

  • 在 Facebook 上分享
  • 在 LinkedIn 上分享
  • 在 X 上分享

Towards Data Science 是一个社区出版物。提交你的见解,以触达全球受众,并通过 TDS 作者支付计划获得报酬。

更新 href 为你的实际提交 URL

为 TDS 写作

✦ 结束 CTA ✦