图片文字提取工具包:基于easyOCR的批量OCR识别与工程化实践
简介这是一份面向需要从图片中批量提取文字的用户准备的离线OCR工具包基于Python与easyOCR库实现适用于64位Windows系统可帮助办公人员、数据整理者及开发者快速完成截图、扫描件等图像的文字抓取无需联网即可运行。压缩包共4862个文件约808.61MB以py源码、pyc字节码、pyd扩展模块和h头文件为主同时包含dll动态库、ttf字体、png图标及txt说明等构成完整的Python运行与识别环境。目前已有1307人学习下载。工具支持中英文等多语言识别可遍历文件夹批量处理图片并允许调整最小字体、检测框精度等参数优化效果包内附easyOCR安装与调用示例便于二次开发或集成到自有项目中同时提供异常捕获与多线程加速思路帮助应对图像质量差、文字排列复杂等实际场景。1. 从一张截图到可编辑文本这个工具包到底解决了什么上周帮同事处理一批扫描版合同对方发来 30 多张手机拍的 PDF要求把里面的条款文字抠出来做比对。手动敲了两页就发现不对劲——错字率太高而且格式全乱。这种场景下图片文字提取工具.zip 就是冲着这个痛点来的它把 OCR 流程里最烦人的环境配置、模型下载、批量处理逻辑打包好了解压就能跑。这个资源包的核心是 easyOCR一个基于 PyTorch 的轻量级 OCR 库支持 80 多种语言中文识别效果在开源方案里属于第一梯队。它适合两类人一是需要快速把图片、截图、扫描件转成文本的开发者二是想研究 OCR 落地但不想从零搭环境的学生或转行者。包里通常包含示例脚本、依赖清单和测试图片省去了自己搜教程、拼代码的时间。如果你之前被 tesseract 的中文识别率折磨过或者用在线 OCR 担心隐私这个包值得拆开看看。2. easyOCR 的选型逻辑与最小可运行环境2.1 为什么是 easyOCR 而不是 tesseract 或 PaddleOCR选 OCR 库这件事我踩过的坑比想象中多。tesseract 胜在轻量但中文需要额外下载语言包而且对倾斜、模糊、复杂背景的图片几乎没法用预处理稍微不到位就满屏乱码。PaddleOCR 精度确实高但依赖 PaddlePaddle 框架安装包大Windows 下偶尔会遇到 DLL 加载问题对新手不太友好。easyOCR 的定位在两者之间底层用 PyTorch模型是 CRNN 加注意力机制中文识别准确率明显优于 tesseract安装只需要 pip 一条命令。它的检测模型 CRAFT 能较好地处理任意方向文字识别模型对印刷体、屏幕截图、文档扫描件都有不错的表现。代价是首次运行会下载约 100MB 的模型文件且推理速度比 PaddleOCR 稍慢但在 CPU 上跑单张图片也就一两秒批量处理时用 GPU 能快 5 到 10 倍。这个工具包的价值在于它把 easyOCR 的安装、模型缓存、批量读取、结果导出这几步串好了。你不需要自己去查 API 文档照着脚本改路径就能用。2.2 环境搭建Python 版本与依赖的硬约束easyOCR 对 Python 版本有要求3.8 到 3.11 都能跑但 3.12 在部分 Windows 环境下会遇到 torch 编译问题。我一般建议用 3.10兼容性最稳。如果你机器上有多个 Python 版本先确认 pip 对应的解释器是对的。# 查看当前 Python 版本确认在 3.8-3.11 之间 python --version # 创建独立虚拟环境避免污染全局包 python -m venv ocr_env # Windows 激活 ocr_env\Scripts\activate # macOS/Linux 激活 source ocr_env/bin/activate # 安装 easyOCR会自动拉取 torch、torchvision、opencv-python 等依赖 pip install easyocr # 如果下载慢可以指定国内镜像源 pip install easyocr -i https://pypi.tuna.tsinghua.edu.cn/simple这里有个细节easyOCR 安装时会自动装 CPU 版 PyTorch。如果你有 NVIDIA 显卡并且想用 GPU 加速需要先卸载 CPU 版再装 CUDA 版否则代码里写了gpuTrue也会报错。具体命令取决于你的 CUDA 版本常见做法是去 PyTorch 官网生成对应安装命令不要直接复制别人的。提示虚拟环境激活后命令行前面会出现(ocr_env)标识。如果没出现说明激活失败后续安装会装到全局环境里容易和已有包冲突。2.3 第一次识别三行代码跑通中文提取环境好了之后先别急着批量处理用一张测试图确认模型能正常下载和推理。工具包里一般有test.jpg或类似文件没有的话自己截一张带文字的图。import easyocr # 初始化 Reader指定中文简体(ch_sim)和英文(en) # gpuFalse 表示用 CPU有显卡且装好 CUDA 版 torch 可改为 True reader easyocr.Reader([ch_sim, en], gpuFalse) # 读取图片detail0 表示只返回文本列表不返回坐标和置信度 result reader.readtext(test.jpg, detail0) # 打印识别结果 for line in result: print(line)第一次运行会看到下载进度条模型文件默认缓存在~/.EasyOCR/model目录下。下载完成后输出应该是图片里的文字内容。如果返回空列表先检查图片路径是否正确、图片里是否有清晰文字。detail0返回的是纯文本列表detail1会返回(坐标, 文本, 置信度)三元组后续做版面分析时需要坐标信息。参数方面[ch_sim, en]表示同时加载中文简体和英文模型识别时会自动判断语种。如果你只处理英文改成[en]能减少模型加载时间。gpu参数在初始化时就要确定中途改不了所以跑之前想清楚用不用显卡。3. 批量处理与结果导出的工程化改造3.1 遍历文件夹把单张识别改成流水线单张识别只是验证实际场景里往往是一个文件夹几十上百张图。直接写个循环调用readtext就行但有几个地方要注意图片格式要统一处理读取失败要跳过而不是中断结果要按文件名对应保存。import easyocr import os import json # 初始化一次复用 Reader 对象避免每张图都重新加载模型 reader easyocr.Reader([ch_sim, en], gpuFalse) # 图片所在文件夹和输出文件夹 input_dir ./images output_dir ./results os.makedirs(output_dir, exist_okTrue) # 支持的图片格式 exts (.jpg, .jpeg, .png, .bmp, .tiff) all_results {} for filename in os.listdir(input_dir): if not filename.lower().endswith(exts): continue filepath os.path.join(input_dir, filename) try: # detail1 返回坐标、文本、置信度方便后续过滤低质量结果 result reader.readtext(filepath, detail1) # 提取文本和平均置信度 texts [item[1] for item in result] confs [item[2] for item in result] avg_conf sum(confs) / len(confs) if confs else 0 all_results[filename] { texts: texts, avg_confidence: round(avg_conf, 4) } print(f{filename}: 识别 {len(texts)} 行平均置信度 {avg_conf:.2f}) except Exception as e: # 单张失败不影响整体流程 print(f{filename}: 处理失败 - {str(e)}) all_results[filename] {error: str(e)} # 结果保存为 JSON方便后续程序读取 with open(os.path.join(output_dir, ocr_results.json), w, encodingutf-8) as f: json.dump(all_results, f, ensure_asciiFalse, indent2)这段代码的关键点在于Reader对象只初始化一次。easyOCR 加载模型需要几秒到十几秒如果放在循环里每张图都重新加载批量处理会慢得让人想砸键盘。另外用try-except包住单张识别遇到损坏图片或权限问题不会导致整个任务挂掉。置信度字段很有用低于 0.5 的结果基本可以判定为噪声后续可以过滤掉。3.2 输出格式选择TXT、JSON 还是带坐标的 CSV工具包默认可能只输出 TXT但实际项目里不同格式对应不同用途。我整理了一个对比表按场景选输出格式包含信息适用场景缺点TXT纯文本按行拼接快速查看、复制粘贴丢失位置和置信度JSON文本、坐标、置信度程序二次处理、结构化存储文件体积大人眼阅读不便CSV文件名、行号、文本、置信度Excel 分析、质量抽检坐标信息需要额外列带框图片原图叠加识别框验证识别效果、汇报演示需要 opencv 绘图处理慢如果只是要文字内容TXT 最省事。但如果你要做版面还原比如判断某行文字在图片中的位置就必须保留坐标。easyOCR 返回的坐标是四个点的列表[[x1,y1],[x2,y2],[x3,y3],[x4,y4]]对应文本框的四个角。用 opencv 画出来就能直观看到哪些区域识别到了、哪些漏了。import cv2 import easyocr reader easyocr.Reader([ch_sim, en], gpuFalse) result reader.readtext(test.jpg, detail1) img cv2.imread(test.jpg) for bbox, text, conf in result: # 将坐标点转为整数并绘制矩形框 pts [(int(p[0]), int(p[1])) for p in bbox] cv2.polylines(img, [np.array(pts)], True, (0, 255, 0), 2) # 在框上方写识别文本 cv2.putText(img, text, (pts[0][0], pts[0][1] - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) cv2.imwrite(result_vis.jpg, img)这段代码依赖 numpy 和 opencv-pythoneasyOCR 安装时会自动带上。cv2.polylines画的是四边形框比矩形更贴合倾斜文字。cv2.putText的中文支持不好如果识别结果含中文写上去会变成问号这时候需要换成 PIL 绘图或者只画框不写字。3.3 参数调优识别精度不够时改什么easyOCR 的readtext方法有几个参数直接影响结果很多人不知道可以调paragraphFalse默认 False设为 True 会把相邻文本行合并成段落适合文章类图片但表格类图片会打乱结构。width_ths0.7控制文本行合并的宽度阈值值越大越容易把相邻文字合并成一行。表格线密集时调小到 0.3 能减少误合并。text_threshold0.7文本检测的置信度阈值调低会检出更多文字但噪声也更多调高则可能漏掉浅色文字。low_text0.4低置信度文本的下限低于此值的区域直接丢弃。图片背景复杂时适当调高到 0.5 能减少误检。mag_ratio1.5图像放大比例对小字号文字有效。把 1.0 改成 1.5 或 2.0 能让小字更清晰代价是处理时间增加。我一般先用默认参数跑一遍看置信度分布。如果大量结果在 0.3 到 0.5 之间说明图片质量或参数需要调整。先试mag_ratio1.5再试text_threshold0.6每次只改一个参数否则不知道是哪个起了作用。4. 避坑与排查那些让识别结果翻车的细节4.1 模型下载卡住或报 SSL 错误现象第一次运行easyocr.Reader()时进度条长时间不动或者抛出SSLError、ConnectionError。原因模型文件托管在境外服务器网络不稳定时下载会中断。另外公司网络如果有 SSL 拦截证书验证会失败。解决手动下载模型文件放到缓存目录。easyOCR 的模型在 GitHub Release 页面文件名类似craft_mlt_25k.pth和zh_sim_g2.pth。下载后放到~/.EasyOCR/modelWindows 是C:\Users\用户名\.EasyOCR\model。如果不知道具体缺哪个看报错信息里的文件名。放好后重新运行代码会直接加载本地文件不再下载。4.2 中文识别结果出现大量空格或乱码现象识别出来的中文每个字之间都有空格或者出现□□□这样的方块。原因一是初始化时语言列表没写对比如写成了[ch_tra, en]但图片是简体二是字体缺失导致部分生僻字无法显示三是图片本身分辨率太低文字糊成一团。解决确认语言代码是ch_sim简体而不是ch_tra繁体。如果是显示问题检查终端或编辑器的字体是否支持中文。分辨率问题只能从源头解决用mag_ratio2.0放大图像再识别或者先用 PIL 做锐化处理。实测 300 DPI 以上的扫描件识别率明显高于 72 DPI 的屏幕截图。4.3 GPU 模式报 CUDA 错误或显存不足现象设置gpuTrue后报AssertionError: Torch not compiled with CUDA enabled或CUDA out of memory。原因安装的是 CPU 版 PyTorch或者显卡显存太小低于 4GB扛不住批量推理。解决先确认 torch 版本运行python -c import torch; print(torch.cuda.is_available())返回 False 说明装的是 CPU 版。卸载后去 PyTorch 官网按 CUDA 版本重新安装。显存不足的话把批量处理改成逐张推理不要一次性把多张图塞进 GPU。另外 easyOCR 初始化时可以指定gpuTrue但推理时用batch_size1控制显存占用。4.4 表格和竖排文字识别错乱现象表格里的文字被合并成一行或者竖排文字识别成横排乱序。原因easyOCR 的检测模型默认按水平方向组织文本行对表格线和竖排布局没有专门处理。解决表格类图片先用 opencv 做形态学操作提取横竖线把单元格切出来单独识别。竖排文字可以在识别前把图片旋转 90 度识别完再转回去。如果表格结构复杂建议换用 PaddleOCR 的表格识别模型easyOCR 在这方面确实不是强项。我一般遇到表格就手动切图虽然笨但结果可控。4.5 置信度虚高但内容错误现象某行文字置信度 0.95但识别结果和原图对不上比如把“未”识别成“末”。原因形近字是 OCR 的经典难题模型对相似字形容易混淆而且置信度只反映模型自己的“信心”不代表绝对正确。解决对关键字段做后处理校验。比如合同里的金额、日期用正则表达式匹配数字模式不符合的标记出来人工复核。另外可以同时跑 easyOCR 和 tesseract对比两者结果不一致的地方重点检查。这个习惯帮我拦下过好几次金额识别错误。5. 进阶技巧用预处理把识别率再拉高一截5.1 图像预处理三板斧灰度、二值化、去噪easyOCR 内部虽然会做归一化但输入图片质量太差时预处理能明显改善结果。我常用的组合是转灰度 → 自适应二值化 → 中值滤波去噪。这套流程对扫描件和手机拍的文档特别有效。import cv2 import numpy as np def preprocess_image(image_path): # 读取图片 img cv2.imread(image_path) # 转灰度减少颜色干扰 gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 自适应二值化对光照不均的图片比全局阈值更稳 binary cv2.adaptiveThreshold( gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, blockSize11, # 邻域大小奇数越大越平滑 C2 # 阈值偏移越大越偏向黑色 ) # 中值滤波去椒盐噪声 denoised cv2.medianBlur(binary, 3) return denoised # 预处理后再送入 easyOCR processed preprocess_image(noisy_doc.jpg) cv2.imwrite(processed.jpg, processed) reader easyocr.Reader([ch_sim, en], gpuFalse) result reader.readtext(processed.jpg, detail0)blockSize和C是两个关键参数。blockSize决定局部阈值的计算范围文字笔画细的图片用 9 或 11笔画粗的用 15 或 21。C是常数偏移值越大二值化后黑色区域越多文字断连时调小到 1 或 2背景噪点多时调大到 3 或 4。这套预处理不是万能的如果原图本身清晰跳过预处理反而更好因为二值化可能把浅色文字直接抹掉。5.2 多语言混合场景的语言代码配置有些图片是中英文混排甚至夹杂日文或韩文。easyOCR 支持同时加载多个语言模型但语言越多加载越慢识别时也可能互相干扰。我的经验是只加载图片里实际出现的语种不要贪多。# 中英混排最常用 reader easyocr.Reader([ch_sim, en], gpuFalse) # 中日英混排加载三个模型初始化时间明显变长 reader easyocr.Reader([ch_sim, en, ja], gpuFalse) # 纯数字和英文速度最快 reader easyocr.Reader([en], gpuFalse)语言代码要写对简体中文是ch_sim繁体是ch_tra日文是ja韩文是ko。如果写错代码初始化时会报ValueError。另外注意同时加载ch_sim和ch_tra没有意义模型会冲突选一个就行。5.3 结果后处理用正则修正常见 OCR 错误OCR 输出里有些错误是规律性的比如数字0和字母O混淆、1和l混淆、中文引号变成英文引号。写几条正则替换能省下大量人工校对时间。import re def postprocess_text(text): # 修正常见数字混淆O-0, l-1仅在数字上下文中 text re.sub(r(?\d)O(?\d), 0, text) text re.sub(r(?\d)l(?\d), 1, text) # 统一引号 text text.replace(, ).replace(, ) text text.replace(, ).replace(, ) # 去除行首行尾多余空格 text text.strip() # 合并被错误拆分的英文单词连字符后换行 text re.sub(r-\n, , text) return text # 对 easyOCR 结果逐行应用 cleaned [postprocess_text(line) for line in result]这些规则不是通用的要根据你的实际数据调整。比如处理发票时金额字段的校验规则又不一样。我一般先跑一批样本把错误结果收集起来看哪些错误反复出现再针对性写正则。不要一上来就写几十条规则很多根本用不上。5.4 验证识别质量的土办法没有标注数据的情况下怎么判断识别结果靠不靠谱我常用两个办法一是随机抽 10 张图把识别文本和原图逐行对照统计错字率二是用detail1的置信度把低于 0.6 的行全部标出来人工检查。如果低置信度行占比超过 20%说明图片质量或参数需要调整别急着批量跑先解决源头问题。还有一个笨但有效的办法把识别结果丢进搜索引擎或拼写检查工具看有没有大量不存在的词组。中文可以用 jieba 分词后统计生僻词比例英文可以用language_tool_python检查语法。这些工具不能替代人工但能快速定位问题集中的区域。从那以后我每次拿到新的图片批次都强制先跑 5 张样本、人工核对、调完参数再批量处理这个习惯帮我省下了大量返工时间。希望帮到你。本文还有配套的精品资源点击获取