2026/10/15 9:17:32

开源OCR工具实战:Tesseract与PaddleOCR实现图片和PDF文字提取

开源OCR工具实战:Tesseract与PaddleOCR实现图片和PDF文字提取 先说明一下这个项目对我来说不算新面孔但每次看到有人把「图片 PDF」里的文字手工一个字一个字敲进电脑我都替他们手疼。日常办公里最烦人的场景之一就是客户发来一份扫描版合同、朋友传几张带文字的截图、或者报销系统里必须上传 PDF 原件但里面全是图片想复制一段文字只能重新打字。更别提那些拍歪了的书上照片横竖颠倒、反光偏色简直是要了老命。这篇文章想聊的就是一套开源 OCR 工具组合的真实用法核心依赖 Tesseract 和 PaddleOCR前者老牌稳健、部署轻量后者中文识别精度高、自带表格还原能力。我会把从环境搭建到图片文字提取、PDF 批量转文字的完整链路都过一遍中间穿插我踩过的坑、调过的参数、以及那些只有长期用 OCR 的人才会注意到的细节。不管你是只想要个能用的命令行工具还是想在 Python 脚本里做点自动化这篇都能让你直接抄作业。1. 给「打工人」的 OCR 需求拆解1.1 图片里文字为什么难提取先说个扎心的事实图片看不懂文字因为屏幕上的图片本质上是一堆像素点。每个像素只有一个颜色数值没有「字符」概念所以你在浏览器里看到 PDF 中的一行字对计算机来说只是几十万个红的绿的蓝的色块排列。要让电脑真正「读」出文字就得靠 OCR——Optical Character Recognition光学字符识别把图像里的字形轮廓还原成 Unicode 字符序列。这套玩意的核心原理并不神秘。第一步是检测从整张图里找出哪些区域有文字、文字的边界框在哪第二步是识别把每个文字区域内的字形裁剪出来交给神经网络或模板特征比对最终映射成字符。听起来简单但真实世界里的图片千奇百怪手机拍的本子自带背景纹路、扫描仪扫出来的合同黑底白字、PPT 导出的 pdf 文字全是矢量……每一类情况对预处理的要求都不一样。我之前接过一个任务客户要求从 300 页的扫描版行业报告中提取所有表格里的金额和日期光是预处理那一步就折腾了两天最后发现最值钱的不是模型本身而是你把图像喂给模型之前做的那套「洗图」流程。1.2 为什么选开源方案而不是在线工具在线 OCR 工具确实方便打开网页传张图就能出文字可一碰敏感信息就完蛋。法院的判决书、公司的财务报表、学校的保密试卷你敢往第三方服务器传吗我是不敢的。把资料传给人家的服务器等于默认「授权」对方存你数据哪怕对方承诺「仅用于识别」协议条款里通常也写了「有权改进服务」这类免责表述细看全是雷。而且在线工具大多有免费额度这个隐形拦路虎免费用户一天只能识别几次超过就要开会员。公司的报销单据一多月月装会员一年下来开销并不小。更头疼的是很多在线 OCR 只支持整页文本输出不保留表格结构、不区分段落层级复制的文字贴进 Excel 后全挤在 A 列里整理起来比打字还费劲。开源方案完全绕开这些问题代码跑在本地数据不出门识别量没有上限加个循环脚本丢一万张图也是按秒算更重要的是Tesseract 和 PaddleOCR 这类项目都有活跃社区随时可以拿到最新模型和算法改进。1.3 打工人最常用的三大场景结合我自己的使用经验打工人学 OCR 最先覆盖的是这几种需求扫描版 PDF 转可检索 PDF/纯文本文档很多财务系统要求上传 PDF 时附带可复制的文字层用开源工具批量处理一行命令搞定。截图文字归档/翻译微信聊天记录、网课截屏、公众号长图OCR 识别后一键复制配合翻译软件做双语对照非常好用。历史纸质资料数字化家里、办公室囤了十几年的旧报纸、老档案用手机拍下来批量识别成文字存档案库查找效率提升几个量级。提示现在很多开源 OCR 工具已经能直接输出带「隐藏文字层」的 PDF也就是说你搜索 PDF 内容时查找范围是覆盖到扫描图片里的文字的。这个功能对我这种天天和旧合同打交道的人简直是救星。2. 开源 OCR 工具箱的选型路线2.1 Tesseract 还是 PaddleOCR说到开源 OCR绕不开两个名字Tesseract 和 PaddleOCR。Tesseract 最早是惠普实验室搞出来的后来 Google 接手并开源授权在 GitHub 上攒了几万星老牌、稳定、文档齐全。它最大的优势是轻量一个安装包几 MB装上就能用命令行调不需要 Python 环境、不需要 GPU跑在十年前的老笔记本上也不卡。缺点是早期版本的中文识别效果确实一般尤其是遇到艺术字、复杂排版、或者底色很花的图片错字率会比较感人。PaddleOCR 是百度飞桨生态里的明星项目GitHub 星标数增长非常快。它走的是深度学习的路子用的是 PP-OCR 系列预训练模型中文识别精度、中文版式还原能力都远超 Tesseract 的老模型。但它对运行环境的要求高一些默认要装 PaddlePaddle 框架Python 版本和 CUDA 版本对不上会比较容易出问题。我的建议是如果你只要处理偶尔几张图或者跑在树莓派这种小设备上直接用 Tesseract 就够了如果每天要处理几十上百页文档尤其是中文文档直接上 PaddleOCR识别质量能省下你不少校对时间。2.2 不同任务该配什么工具这里我整理一个我自己的选型表格适应不同场景任务场景推荐工具主要理由命令行快速识别单张截图Tesseract安装简单调用快单张图秒出结果批量扫描版 PDF 转文本PaddleOCR中文识别精度高支持批量处理脚本手机拍图书/笔记转文字PaddleOCR 图像预处理透视矫正、去阴影能力更强表格数据提取为 ExcelPaddleOCR 表格结构模型自带表格检测与单元格还原老报纸/老旧字体识别Tesseract 指定语言包对传统字形的兼容性好无 Python 环境的 Windows 电脑Tesseract 独立安装版安装即用图形界面可选当然这不是绝对的你也可以像我一样两个都装Tesseract 当「快速随手工具」PaddleOCR 当「正式业务流水线」不同任务选择不同入口拿捏得很死。2.3 关键参数怎么选语言包、输出格式、精度权衡不管用哪个工具你最先要配的是语言包。Tesseract 支持多语言但默认只装英文要识别中文得专门下载 chi_sim 语言包装好后还要在命令行里-l chi_simeng这样指定中英混排时才不丢内容。PaddleOCR 则不用这么麻烦PP-OCRv4 模型本身就支持中文和英文切换语言包在配置里传个参数就行。其次要留意输出格式。Tesseract 常规输出是纯文本但可以通过配置输出 hOCR 或 ALTO XML里面包含每个文字的坐标框。这个信息对保留排版很有用——比如你想还原原文的段落缩进、列表层级纯文本输出做不到但结合坐标信息就能部分重建。PaddleOCR 默认返回字典格式包含文本内容和坐标框通常是大方框做进一步结构分析很方便。最后是精度与速度的权衡。识别引擎大体上有两种路线一种是传统的模板特征匹配比如 Tesseract 的部分模式CPU 上跑得快、但遇到字体变体容易炸另一种是深度学习端到端识别如 PaddleOCR 的文本识别模型需要更多计算资源但泛化能力强很多。像我这种追求性价比的打工人做法是普通图片两个字库模型都试一遍选错字少的那条路批量大数据时才开高性能模式。本质上就是拿时间换精度别让机器闲着。3. 手把手实操从安装到跑通全流程3.1 环境准备与安装我先展示在 Windows 上的 Tesseract 安装流程这是最没有门槛的路径。去 GitHub 的 tesseract-ocr/tesseract 仓库找到 Windows 安装包下载64 位 exe一路点 Next 装完。这里有一个细节安装时勾选项里有一页让选 Additional Language Data一定要展开勾选Chinese (Simplified)不然后面识别中文得返工。装完打开 PowerShell输tesseract --version能看到版本号就说明装好了。如果你偏爱命令行又能忍 Python 环境那就按 Python 路线来。先建一个虚拟环境避免污染系统 Pythonpython -m venv ocr_env ocr_env\Scripts\activate # Windows 下激活虚拟环境 pip install paddlepaddle paddleocrPaddleOCR 的 pip 包通常会把依赖的深度学习框架一起装好版本匹配问题概率不算低不过官方文档写得很清楚遇到安装报错照抄提 issue 也很快。我当时是在 Mac 上装的前后花了二十分钟基本没踩坑Windows 上如果提示缺什么 DLL把 Microsoft Visual C Redistributable 装上就好。3.2 命令行三秒识图Tesseract 快速上手装好 Tesseract 之后先拿一张最简单的纯白底黑字截图试手。假如文件叫test.png跑这条命令tesseract test.png output -l chi_sim这样会生成一个output.txt内容就是识别出的文字。如果图片里同时有中英文可以把语言包合并指定tesseract test.png output -l chi_simeng如果你发现识别效果不太行可以先手动调整图像质量再喂喂看。我个人实测下来旋转校正、去噪、二值化这三板斧对识别率的提升最明显。比如用 ImageMagick 把图片先放大两倍再识别边缘更平滑小字号文字识别率能提升一截magick test.png -resize 200% -colorspace Gray -depth 8 test_big.png tesseract test_big.png output -l chi_sim为什么放大有效因为 OCR 模型的训练数据大多包含较大的字符样本尺寸太小的字符在缩放后笔画细节模糊识别器容易把「因」成「田」、「岁」成「歹」。放大虽然不增加信息量但能把像素网格铺得更密让拓扑特征更稳定。3.3 Python 脚本处理多张图片和 PDF 扫描件只玩命令行虽然爽但要批量处理时还是得写脚本。下面这个 Python 脚本用 PaddleOCR 批量识别一个文件夹里的所有图片结果输出到一个汇总文本文件里适合处理「一堆微信截图归档」或「书页扫描件」场景import os from paddleocr import PaddleOCR ocr PaddleOCR(use_angle_clsTrue, langch) input_dir images output_file all_text.txt with open(output_file, w, encodingutf-8) as out: for name in sorted(os.listdir(input_dir)): if not name.lower().endswith((.png, .jpg, .jpeg, .bmp, .tif)): continue path os.path.join(input_dir, name) result ocr.ocr(path, clsTrue) out.write(f\n {name} \n) for line in result: for item in line: out.write(item[1][0] \n) out.flush() print(fDone: {name})这段逻辑不难但有两个隐藏注意点use_angle_clsTrue是开启方向分类器能自动识别被转了 180 度/90 度的文字方向。我拍书时经常拍歪这个开关能省掉不少手动旋转的功夫。写文件时用encodingutf-8否则在 Windows 下默认编码容易乱码尤其是中文文本打开全是「锟斤拷」那叫一个酸爽。扫描版 PDF 要转文本比起先把 PDF 转成图片再跑 OCR 的拆两步法更推荐的是直接让 PaddleOCR 支持 PDF 输入不过不同版本对这个功能的支持不太一样。我之前用的是一个更老的方案PyMuPDF 把 PDF 每页转成高分辨率 PNG丢给 OCR再拼回文本。这样好处是对 PDF 里字体乱码、表格复杂的情况都能手动控制每一页的处理方式。给你一段我用 PyMuPDF 做 PDF 拆页的 Python 片段import fitz # PyMuPDF doc fitz.open(scan.pdf) for page_num in range(doc.page_count): page doc[page_num] pix page.get_pixmap(matrixfitz.Matrix(2.0, 2.0)) # 2倍分辨率 pix.save(fpage_{page_num:03d}.png)Matrix(2.0, 2.0)意味着把页面渲染成两倍像素尺寸PDF 里若隐若现的小字经放大后会清晰许多。这一步相当于把 72 DPI 的屏幕显示提升到接近 150 DPI 的打印效果OCR 识别率提升是肉眼可见的。3.4 表格识别从图片直接到 Excel如果你和我一样经常要处理「报销单里日期/金额录入」「学生成绩表转电子版」这类任务纯文本输出根本不够用你真正想要的是结构化的表格数据。这时候 PaddleOCR 的表格结构识别模型就派上用场了。基础用法很简单在PaddleOCR初始化时指定tableTruefrom paddleocr import PaddleOCR ocr PaddleOCR(use_angle_clsTrue, langch, tableTrue) result ocr.ocr(table.jpg, clsTrue)返回结果里除了每行文字内容还会有表格的 HTML 结构字符串。热门做法是把 HTML 表格字符串存成.html文件再用 pandas 转成 Excel。我之前写过一个简化版流程直接把结果导出为 csvimport pandas as pd html_data result[table_res][0][html] # 伪代码示意具体字段以实际返回为准 dfs pd.read_html(html_data) for i, df in enumerate(dfs): df.to_csv(ftable_{i}.csv, indexFalse, encodingutf-8-sig)注意我用的是utf-8-sig因为 Excel 直接打开 UTF-8 的 CSV 经常会乱码而带 BOM 的 UTF-8 则稳如老狗。提示表格识别对图片质量很敏感拍斜了、光照不均匀都会导致表格线断裂。在拍照后先跑一次透视矫正把四个角映射到标准矩形再喂模型成功率会提升一个档次。4. 疑难杂症终极排查手册4.1 识别结果全是乱码多半是编码问题「乱码」这个坑我踩得最深的就是 Windows 控制台。Tesseract 输出的 txt 文件默认以 UTF-8 编码写盘但 Windows 记事本老版本不一定认打开就显示成乱码。在 Windows 下处理文本输出统一原则是存文件用 UTF-8 加 BOM打印到屏幕用errorsignore。Python 写 CSV 用encodingutf-8-sig写文本用encodingutf-8并在读的时候也指定相同编码基本上不会出幺蛾子。还有一个隐蔽情况是语言包冲突比如 Tesseract 装了多语言包但你调用时-l chi_sim拼错了它会静默回退到英文模式结果中文全变拼音或乱码。这个错误不报错得靠你自己检查输出里有没有大量英文字母混杂。4.2 韩文识别不了先看模型支持清单热词里有条「以下ocr代码识别不了韩文: from paddlex import create_pipeline...」这个问题很有代表性。很多开源 OCR 模型默认只支持中英双语韩语、日语、法语都得手动加载对应语言包。Tesseract 可以从 GitHub 语言包仓库下载kor.traineddata放进 tessdata 目录再指定-l kor。PaddleOCR 则要根据你用的版本选择多语言模型PP-OCRv3 之后对韩文的支持也逐步完善但要确认你安装的模型文件确实包含韩文字符集。识别不了还有一个常见原因是字体韩文字形有自己独特的字符组合方式如果你用的是 Tesseract 的老旧模型遇到刚推出的新字体也会识别不佳这时候优先换模型版本。4.3 图片清晰度够了为何仍识别错字我遇到过很多次自认为「图很清晰了」但 OCR 还是出错的案例最后发现全都是同一个原因背景干扰。底色花里胡哨、有水印、有下划线都会让字符边界被破坏。在这种图片上先做图像预处理比换任何模型都有效转灰度 大津法二值化把彩色图压成纯黑纯白去掉背景纹理。Tesseract 对二值图最友好PaddleOCR 对灰度图也能处理得不错。去盐椒噪声扫描件上很多小黑点小白点用中值滤波处理后再送识别。剪裁边界阴影、页眉页脚、手写批注全部裁掉减少干扰区域。我自己印象最深的一次是在处理一份「银行回单」照片时背景有网格底纹Tesseract 把「壹仟贰佰」识别成「壹仟贰伯」怎么调参数都不对最后把图片转灰度再做自适应阈值问题一下就解决了。4.4 性能太慢怎么办并发、分块、小图合并别想着白嫖 GPU我用 CPU 跑 PaddleOCR 时一张 A4 图片大概要 0.5~2 秒批量 1000 张图跑起来也是几分钟的事说不上慢。但如果你要处理的是超高分辨率长图比如公众号长截图PaddleOCR 会因显存不足直接崩掉。这时候要分块把长图切成若干横条每条高度 800~1200 像素分别识别再合并输出。切块时注意保留一点重叠区域避免把文字从中间拦腰截断。批量处理时还可以用multiprocessing或concurrent.futures做多进程并发每个进程一个 PaddleOCR 实例。多说一句PaddleOCR 实例初始化比较吃内存你起太多进程容易内存爆炸实测下来 4 个进程是我的老笔记本极限再往上反而因频繁 GC 导致效率下降。4.5 避坑清单速查表坑点解决方案输出中文乱码文件写 UTF-8 加 BOM读取指定 encoding韩文/日语识别不了检查语言包是否安装调用时指定正确语言参数底色干扰文字先灰度化和自适应阈值再交给 OCRPDF 文字是图片先用 PyMuPDF 渲染成高分辨率 PNG再识别长图显存溢出裁剪成多个小图分块识别重叠区域 10%~15%识别结果顺序乱开启坐标框按 y 坐标排序后再按 x 坐标排序批量处理内存不足用一个常驻进程池每个进程实例复用别频繁创建Excel 打开 CSV 乱码导出 CSV 用 encodingutf-8-sig5. 把 OCR 变成自动化的进阶玩法5.1 文件夹监控 自动转文字最实用的一套自动化玩法是用 watchdog 监听一个文件夹往里面丢一张图片识别结果自动存到另一个目录。比如公司用的扫描仪支持扫描到指定网盘目录你放个监听脚本扫完一份文件文字稿自动生成还能顺手按日期归档到子文件夹。简单的代码框架如下import time from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler from paddleocr import PaddleOCR class OcrHandler(FileSystemEventHandler): def __init__(self): self.ocr PaddleOCR(use_angle_clsTrue, langch) def on_created(self, event): if event.is_directory: return if event.src_path.lower().endswith((.png, .jpg, .jpeg)): result self.ocr.ocr(event.src_path, clsTrue) text \n.join([item[1][0] for line in result for item in line]) with open(event.src_path .txt, w, encodingutf-8) as f: f.write(text) print(fProcessed: {event.src_path})watchdog 库不是标准库需要单独pip install watchdog。这段代码真正的价值在于你只需要把图片拖进指定文件夹其他什么都不用管这对于非程序员同事非常友好。我帮财务小姐姐搭过一个同款她从此再也不用问「这堆 PDF 怎么转文字」了。5.2 结合 Word/Excel 宏和可视化工具有些朋友完全不熟悉 Python那也没关系。Tesseract 除了命令行还有不少图形化前端的开源项目比如 Windows 上的gImageReader、Mac 上的TextShot界面比命令行友好太多直接拖图、选语言、出文本一条龙。如果已经装了 Microsoft Office另一个思路是写一个 VBA 宏调用本地 tesseract.exe 做识别。当然VBA 直接调外部 exe 有点绕你要用Shell函数调命令再把结果读回 Excel 单元格比较繁琐。我更推荐的做法是把 Python 打包成 exe 或脚本配合 Excel 的「Power Query 读取文件夹」功能识别结果写入 CSVExcel 再自动刷新加载整套链路全自动而且完全不依赖第三方在线服务。5.3 如何用开源 OCR 构建自己的知识库如果你手头资料特别多可以把识别文字汇总成 Markdown 文件放到 Obsidian、思源笔记这类本地知识库中然后用标签管理类型合同、发票、读书笔记、行业内参。我自己的流程是扫描/拍照 - 自动 OCR - 生成带原始图片链接的 Markdown - 导入知识库 - 全文搜索。这样做的最大好处是几年前的资料也能在几秒内搜到关键词再也不用凭记忆翻箱倒柜找纸质版了。一个容易忽略的细节是文件名命名规范我建议统一用日期内容摘要例如2024-06-15_劳动合同补充协议.md。否则识别文本生成一堆page_023.txt后期检索会让人崩溃。顺手在脚本里把文件名按 OCR 结果首行自动重命名非常省心。6. 我对这套工作流的真实体会开场我说自己不是第一次碰 OCR老实说这三年来我前前后后折腾过 Tesseract、PaddleOCR、还有各种商业 SDK最终沉淀下来的工作流大概是这样日常单张图我都是用 Tesseract 命令行配-l chi_simeng干净利落三秒出结果不占内存。批量文档尤其是扫描版 PDF我会用 PyMuPDF 拆页 PaddleOCR 识别 手动校验三件套虽然耗时多一点但正确率远超传统方案。遇到表格直接上 PaddleOCR 表格识别输出 CSV 再交给 Excel 二次清洗。最后所有识别结果统一落到本地知识库按日期和主题归档。最后想分享一个小技巧OCR 从来不是「把图片丢进去、拿文字出来」这么简单预处理和后处理都占了一半功夫。图片拍歪了就先校正光线暗就提亮再二值化识别结果过于混乱就用坐标重新排序如果你愿意花十分钟在「喂给 OCR 之前把图洗得干干净净」你的识别准确率能比裸跑高 15%~20%这买卖划算得很。这套开源工具我现在基本是每天都用遇到新的疑难杂症也总能在 GitHub issues 或社区讨论里找到答案。如果你也是被 PDF 和图片里的文字折磨的打工人建议从现在开始搭一套自己的 OCR 流水线——我相信你会回来谢我的。