战队动态 / 2025-12-02 06:32:10
Python 进阶!实现从任何图像中提取文字,轻松提取图片中的文本!平时工作里是不是经常遇到这种麻烦:别人发的扫描件 PDF、截图里的文字,想复制却只能手动敲?要是文字多,敲到手酸还容易错。今天就教你用 Python 搞定这个问题 —— 不管是普通图片、多语言文字(英语、俄语都能搞),还是 PDF 扫描件,都能自动提取文字,代码直接就能跑,新手也能学会!
一、先搞懂核心工具:我们要用哪些 “帮手”?在动手前,先明白我们依赖的几个关键工具,缺一不可:
工具 / 库
作用说明
Tesseract OCR
核心的 “文字识别引擎”,开源免费,支持多语言,是整个功能的基础
pytesseract
Python 库,用来 “调用” Tesseract 引擎(相当于 Python 和 Tesseract 之间的桥梁)
Pillow(PIL)
Python 图片处理库,用来打开图片、做预处理(比如转黑白图提高识别率)
pdf2image
Python 库,把 PDF 扫描件转成一张张图片(因为 PDF 扫描件本质是图片打包)
Poppler
辅助工具,pdf2image 依赖它才能转 PDF 为图片,必须装
简单说:Tesseract 负责 “认文字”,pytesseract 负责 “让 Python 指挥 Tesseract”,Pillow 负责 “处理图片”,pdf2image+Poppler 负责 “拆 PDF 扫描件”。
二、环境准备:一步步装工具(Mac/Windows 都讲清)这一步最关键!少装一个或配置错,后面代码就跑不起来。按系统一步步来,别跳步。
2.1 先装核心引擎:Tesseract OCR情况 1:Mac 系统Mac 用户需要先装「Homebrew」(如果没装过),打开终端,复制下面的命令回车:
代码语言:python复制# 装Homebrew(如果没装)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"装完 Homebrew,再装 Tesseract 和多语言包:
代码语言:python复制# 装Tesseract核心
brew install tesseract
# 装所有语言包(包括英语、俄语、中文等,一步到位)
brew install tesseract-lang装完后,终端输tesseract -v,能看到版本号就说明成了。
情况 2:Windows 系统下载 Tesseract 安装包:打开这个链接,往下滑找到 “Latest release”,下载带 “64-bit” 的安装包(比如tesseract-ocr-w64-setup-5.3.3.20231005.exe)。双击安装:关键步骤—— 安装时一定要勾选 “Add Tesseract to PATH”(让电脑全局能找到 Tesseract),如果没勾,后面要手动配环境变量。验证:打开 CMD(命令提示符),输tesseract -v,能看到版本号就成。如果没勾 Add to PATH,手动配环境变量:
右键 “此电脑”→“属性”→“高级系统设置”→“环境变量”→在 “系统变量” 里找 “Path”→“编辑”→“新建”,把 Tesseract 的安装目录(比如C:Program FilesTesseract-OCR)粘贴进去→一路点 “确定”。配完要重启 CMD/IDE,不然不生效!2.2 装 Python 库和 Poppler(处理图片 / PDF)第一步:装 Python 库打开终端 / CMD,输下面的命令,装 3 个库:
代码语言:python复制pip install pytesseract pillow pdf2image第二步:装 Poppler(PDF 转图片用)pdf2image 库需要 Poppler 才能工作,继续按系统装:
系统
安装方法
Mac
终端输brew install poppler,直接搞定
Windows
下载压缩包:打开这个链接,下载最新的 “poppler-xx.xx.xx_x86_64.tar.xz”2. 解压:把压缩包解压到一个路径(比如C:poppler),记住解压后里面的 “bin” 文件夹路径(比如C:popplerpoppler-24.02.0bin)3. 配环境变量:和 Tesseract 一样,把 “bin” 路径加入系统变量的 “Path”,然后重启 CMD/IDE2.3 验证环境是否 OK打开 Python 终端(或 IDE 里新建个.py 文件),跑下面的代码:
代码语言:python复制from PIL import Image
import pytesseract
# 随便找张有英文的图片,替换成你的图片路径
img_path = "test_en.png"
# 打开图片并识别(默认英语)
text = pytesseract.image_to_string(Image.open(img_path), lang="eng")
print(text)如果能打印出图片里的英文,说明环境没问题!如果报错,回头查前面的步骤(尤其是环境变量)。
三、入门:单张图片识别(英语 + 多语言)先从简单的单张图片入手,学会基础用法,再进阶批量处理。
3.1 识别英语图片(默认支持)代码超简单,注释写得很清楚:
代码语言:python复制# 导入需要的库
from PIL import Image # 处理图片
import pytesseract # 调用Tesseract
# 1. 定义图片路径(替换成你自己的图片路径,支持png、jpg、jpeg)
image_path = "english_image.jpg"
# 2. 打开图片
img = Image.open(image_path)
# 3. 调用Tesseract识别文字(lang="eng"表示英语,默认也是eng,可省略)
# 这里加了encoding='utf-8',避免中文乱码(虽然这里是英语,但养成习惯)
text = pytesseract.image_to_string(img, lang="eng", encoding='utf-8')
# 4. 打印结果
print("识别到的文字:")
print("-" * 50) # 分隔线,看起来清楚
print(text)运行步骤:
找一张有英语的图片(比如截图、扫描件),改名为english_image.jpg,和代码放同一文件夹;运行代码,就能看到图片里的英文被提取出来了。3.2 识别多语言(比如英语 + 俄语)要识别其他语言,得先确认 “语言代码”,再装对应语言包(Mac 之前装了tesseract-lang,Windows 要手动下)。
第一步:常用语言代码表记不住没关系,收藏这个表:
语言
Tesseract 语言代码
说明
英语
eng
默认自带,不用额外装
简体中文
chi_sim
需要装语言包
俄语
rus
需要装语言包
日语
jpn
需要装语言包
法语
fra
需要装语言包
德语
deu
需要装语言包
第二步:Windows 手动装语言包(Mac 跳过)打开Tesseract 语言包仓库;搜索语言代码对应的文件,比如俄语搜 “rus”,找到rus.traineddata;点 “Download” 下载,把文件放到 Tesseract 的tessdata目录(比如C:Program FilesTesseract-OCRtessdata)。第三步:多语言识别代码比如识别一张既有英语又有俄语的图片:
代码语言:python复制from PIL import Image
import pytesseract
image_path = "eng_rus_image.png" # 你的双语图片路径
img = Image.open(image_path)
# 关键:lang参数用+连接多个语言代码
text = pytesseract.image_to_string(img, lang="eng+rus", encoding='utf-8')
print("双语识别结果:")
print("-" * 50)
print(text)运行后,就能同时提取出英语和俄语文字了。
四、进阶:封装 ImageReader 类(批量 + 复用)写代码不能每次都复制粘贴,我们把识别逻辑封装成一个类,以后用的时候直接调用,支持单张、批量、PDF 处理,还能配置语言和保存结果。
这个类的代码直接能跑,注释写得很详细,你只需要改路径就行:
代码语言:python复制import os # 处理文件/文件夹路径
from PIL import Image # 处理图片
import pytesseract # 调用Tesseract
from pdf2image import convert_from_path # PDF转图片
class ImageReader:
def __init__(self, lang='eng', output_dir=None):
"""
初始化ImageReader(创建实例时调用)
:param lang: 识别语言,默认英语(eng),多语言用+连接(如'eng+rus')
:param output_dir: 结果保存目录,None则不保存,默认None
"""
self.lang = lang # 保存语言参数
self.output_dir = output_dir # 保存结果目录
# 如果指定了保存目录,不存在就自动创建
if self.output_dir and not os.path.exists(self.output_dir):
os.makedirs(self.output_dir)
print(f"创建结果保存目录:{self.output_dir}")
def _preprocess_image(self, image):
"""
【私有方法】图片预处理:灰度化+二值化,提高识别率(不用手动调用)
原理:彩色图干扰多,转黑白图后文字更突出
:param image: PIL.Image对象
:return: 预处理后的PIL.Image对象
"""
# 1. 转灰度图(L模式:每个像素0-255,0是黑,255是白)
gray_img = image.convert('L')
# 2. 二值化:把灰度图变成纯黑白(阈值127,可根据图片调整)
# 像素值>127设为255(白),否则0(黑),文字更清晰
threshold = 127
binary_img = gray_img.point(lambda x: 255 if x > threshold else 0)
return binary_img
def read_single_image(self, image_path, preprocess=True, save_result=False):
"""
识别单张图片
:param image_path: 图片路径(支持png、jpg、jpeg等)
:param preprocess: 是否预处理图片,默认True(推荐开)
:param save_result: 是否保存结果到文件,默认False
:return: 识别到的文字字符串
"""
# 检查图片是否存在
if not os.path.exists(image_path):
raise FileNotFoundError(f"图片找不到:{image_path}")
# 打开图片(捕获异常,避免图片损坏报错)
try:
img = Image.open(image_path)
except Exception as e:
raise ValueError(f"打开图片失败:{e}")
# 图片预处理(如果开启)
if preprocess:
img = self._preprocess_image(img)
# 调用Tesseract识别文字(捕获常见错误)
try:
text = pytesseract.image_to_string(img, lang=self.lang, encoding='utf-8')
except pytesseract.TesseractNotFoundError:
raise Exception("没找到Tesseract!先装Tesseract并配环境变量")
except Exception as e:
raise Exception(f"识别失败:{e}")
# 保存结果(如果开启且指定了目录)
if save_result and self.output_dir:
# 取图片文件名(不含后缀),比如"test.png"→"test"
file_name = os.path.splitext(os.path.basename(image_path))[0]
# 结果文件路径:保存目录/文件名_result.txt
result_path = os.path.join(self.output_dir, f"{file_name}_result.txt")
# 用utf-8编码保存,避免乱码
with open(result_path, 'w', encoding='utf-8') as f:
f.write(text)
print(f"结果已保存到:{result_path}")
return text
def read_batch_images(self, folder_path, preprocess=True, save_result=True):
"""
批量识别文件夹下所有图片
:param folder_path: 图片文件夹路径
:param preprocess: 是否预处理,默认True
:param save_result: 是否保存结果,默认True
:return: 字典,key=图片路径,value=识别结果
"""
# 检查文件夹是否存在
if not os.path.isdir(folder_path):
raise NotADirectoryError(f"文件夹找不到:{folder_path}")
# 支持的图片格式(小写,避免漏判)
supported_formats = ('.png', '.jpg', '.jpeg', '.bmp', '.tiff')
# 存储所有结果
batch_result = {}
# 遍历文件夹里的所有文件
for file_name in os.listdir(folder_path):
# 只处理支持的图片格式
if file_name.lower().endswith(supported_formats):
file_path = os.path.join(folder_path, file_name)
print(f"正在处理:{file_path}")
# 调用单张图片识别方法
try:
text = self.read_single_image(
file_path, preprocess=preprocess, save_result=save_result
)
batch_result[file_path] = text
print(f"处理完成:{file_name}")
except Exception as e:
batch_result[file_path] = f"处理失败:{e}"
print(f"处理失败:{file_name} → {e}")
return batch_result
def read_pdf_scan(self, pdf_path, dpi=300, preprocess=True, save_result=True):
"""
识别PDF扫描件(本质是图片组成的PDF)
:param pdf_path: PDF文件路径
:param dpi: 转图片的分辨率,dpi越高越清晰,默认300(推荐)
:param preprocess: 是否预处理,默认True
:param save_result: 是否保存结果,默认True
:return: 字典,key=页码(从1开始),value=该页识别结果
"""
# 检查PDF是否存在
if not os.path.exists(pdf_path):
raise FileNotFoundError(f"PDF找不到:{pdf_path}")
# 把PDF转成图片(每页一张),依赖Poppler
try:
# dpi=300:分辨率,比默认150更清晰,识别率更高
pages = convert_from_path(pdf_path, dpi=dpi)
print(f"PDF共{len(pages)}页,已转成图片")
except Exception as e:
raise Exception(f"PDF转图片失败:{e}(可能没装Poppler或没配环境变量)")
# 存储每页结果
pdf_result = {}
# 遍历每页图片(page_num从1开始)
for page_num, page_img in enumerate(pages, start=1):
print(f"正在处理PDF第{page_num}页")
# 图片预处理
if preprocess:
page_img = self._preprocess_image(page_img)
# 识别文字
try:
text = pytesseract.image_to_string(page_img, lang=self.lang, encoding='utf-8')
pdf_result[page_num] = text
print(f"PDF第{page_num}页处理完成")
except Exception as e:
pdf_result[page_num] = f"处理失败:{e}"
print(f"PDF第{page_num}页处理失败:{e}")
# 保存PDF识别结果(合并所有页)
if save_result and self.output_dir:
file_name = os.path.splitext(os.path.basename(pdf_path))[0]
result_path = os.path.join(self.output_dir, f"{file_name}_pdf_result.txt")
with open(result_path, 'w', encoding='utf-8') as f:
for page_num, text in pdf_result.items():
f.write(f"=== PDF第{page_num}页 ===n")
f.write(text)
f.write("nn") # 每页之间空两行,方便阅读
print(f"PDF结果已保存到:{result_path}")
return pdf_result4.2 如何使用这个类?(示例代码)把上面的类代码保存为ocr_tool.py,然后新建一个main.py,写调用代码:
代码语言:python复制# main.py
from ocr_tool import ImageReader # 导入我们封装的类
if __name__ == "__main__":
# 1. 初始化ImageReader:识别英语+俄语,结果保存到"ocr_results"文件夹
# 如果你要识别中文,把lang改成"chi_sim",记得装中文语言包
reader = ImageReader(lang="eng+rus", output_dir="ocr_results")
# ------------------- 示例1:识别单张图片 -------------------
print("=== 示例1:单张图片识别 ===")
single_img_path = "test_eng_rus.png" # 你的图片路径
try:
# 识别并保存结果
single_text = reader.read_single_image(single_img_path, save_result=True)
print("识别结果:")
print("-" * 50)
print(single_text)
except Exception as e:
print(f"单张图片处理出错:{e}")
# ------------------- 示例2:批量识别图片 -------------------
print("n=== 示例2:批量识别图片 ===")
batch_folder = "test_images" # 你的图片文件夹路径(里面全是图片)
try:
batch_result = reader.read_batch_images(batch_folder)
# 打印汇总结果(只打印前100个字符,避免输出太长)
print("n批量处理汇总:")
for img_path, text in batch_result.items():
print(f"图片:{os.path.basename(img_path)}")
print(f"结果:{text[:100]}..." if len(text) > 100 else f"结果:{text}")
print("-" * 30)
except Exception as e:
print(f"批量处理出错:{e}")
# ------------------- 示例3:识别PDF扫描件 -------------------
print("n=== 示例3:PDF扫描件识别 ===")
pdf_path = "test_scan.pdf" # 你的PDF扫描件路径
try:
pdf_result = reader.read_pdf_scan(pdf_path)
# 打印汇总结果
print("nPDF处理汇总:")
for page_num, text in pdf_result.items():
print(f"第{page_num}页:{text[:100]}..." if len(text) > 100 else f"第{page_num}页:{text}")
print("-" * 30)
except Exception as e:
print(f"PDF处理出错:{e}")运行步骤:
准备好测试文件:一张双语图片(test_eng_rus.png)、一个图片文件夹(test_images)、一个 PDF 扫描件(test_scan.pdf);运行main.py,就能看到结果,同时在ocr_results文件夹里找到保存的文本文件。五、优化:提高识别准确率的小技巧有时候识别结果会有乱码或错字,主要是图片质量问题,试试这些优化方法:
5.1 优化图片预处理我们的类里已经有 “灰度化 + 二值化”,但可以根据图片调整参数:
调整二值化阈值:如果图片偏暗,把_preprocess_image里的threshold改小(比如 100);如果偏亮,改大(比如 150)。降噪:如果图片有杂点,加一步降噪,比如用 Pillow 的filter:代码语言:python复制from PIL import ImageFilter # 导入滤镜模块
def _preprocess_image(self, image):
gray_img = image.convert('L')
# 加一步高斯模糊降噪(可选,根据图片情况用)
blurred_img = gray_img.filter(ImageFilter.GaussianBlur(radius=0.5))
# 再二值化
threshold = 127
binary_img = blurred_img.point(lambda x: 255 if x > threshold else 0)
return binary_img5.2 提高图片分辨率普通图片:用图片编辑工具放大(比如 Photoshop、在线工具),保持清晰度。PDF 扫描件:转图片时把dpi设高,比如dpi=600(但会变慢,300 足够日常用)。5.3 选择更精准的语言包比如识别中文,用chi_sim(简体)而不是chi_tra(繁体);识别俄语用rus,别用其他相近语言的代码。
六、常见问题与解决方法(避坑指南)这部分是重点!新手最容易踩这些坑,收藏好:
常见错误 / 问题
可能原因
解决方法
TesseractNotFoundError
没装 Tesseract;2. 装了但没配环境变量按前面步骤装 Tesseract;2. 配环境变量后重启 IDE;3. 手动指定路径:pytesseract.pytesseract.tesseract_cmd = r'C:Program FilesTesseract-OCRtesseract.exe'(Windows)PopplerNotInstalledError
没装 Poppler 或没配环境变量
按步骤装 Poppler;2. 配环境变量后重启 IDE;3. 转 PDF 时指定 Poppler 路径:pages = convert_from_path(pdf_path, poppler_path=r'C:popplerbin')(Windows) 多语言识别没效果(全是英语)
没装对应语言包;2. lang 参数写错 Windows:下语言包放 tessdata;Mac:brew install tesseract-lang;2. 查语言代码表,比如俄语是rus不是russian 识别结果是乱码 / 空白
图片模糊 / 分辨率低;2. 编码问题 做图片预处理(灰度化 + 二值化);2. 保存结果时用encoding='utf-8';3. 提高图片分辨率 打开图片报错 “cannot identify image file”
图片损坏或格式不支持
用图片工具打开验证是否完好;2. 转成 png/jpg 格式再试 环境变量配置后还是报错
没重启 IDE 或终端
环境变量修改后,必须重启 PyCharm、VS Code 等 IDE,或者重启 CMD,不然不生效
七、OCR 相关面试题与回答技巧如果面试时被问到相关问题,这么回答,显得你有实战经验:
面试题 1:你用 Python 做过图像文字提取吗?具体用了哪些工具?回答:做过。核心用的是开源的 Tesseract OCR 引擎,Python 这边用 pytesseract 库调用 Tesseract,用 Pillow 处理图片(打开、预处理)。如果要处理 PDF 扫描件,会用 pdf2image 把 PDF 转成图片,这个库需要依赖 Poppler 工具。流程是:先装工具并配置环境,然后预处理图片(灰度化、二值化),再调用 Tesseract 识别,最后输出结果。我还封装过一个 ImageReader 类,支持单张、批量、PDF 处理,方便复用。
面试题 2:Tesseract 怎么支持多语言?比如英语和中文同时识别。回答:首先 Tesseract 默认只有英语包,其他语言需要单独装。Mac 用brew install tesseract-lang就能装所有语言包;Windows 要去 GitHub 的 tessdata 仓库下载对应语言的 traineddata 文件(比如中文是 chi_sim.traineddata),放到 Tesseract 的 tessdata 目录。然后调用时指定 lang 参数,多语言用 + 连接,比如lang='eng+chi_sim',这样就能同时识别英语和中文了。
面试题 3:如何提高 OCR 的识别准确率?回答:主要从图片预处理和工具配置入手。比如:1. 图片预处理,把彩色图转灰度图、二值化,减少干扰;2. 提高图片分辨率,比如 PDF 转图片时设 dpi=300;3. 选择精准的语言包,避免用错代码;4. 如果图片有杂点,加高斯模糊降噪;5. 确保 Tesseract 和语言包是最新版本,修复旧版本的 bug。这些方法能解决大部分日常场景的准确率问题。
面试题 4:PDF 扫描件和普通 PDF 有什么区别?怎么处理 PDF 扫描件的文字提取?回答:普通 PDF 是文本型的,能直接复制文字;PDF 扫描件是图像型的,本质是把图片打包成 PDF,不能直接读文字。处理流程是:先用 pdf2image 库把 PDF 的每一页转成图片,这个库需要 Poppler 支持;转图片时设合适的 dpi(比如 300)提高清晰度;然后对每张图片做预处理(灰度化、二值化);再用 pytesseract 识别文字;最后把所有页的结果合并,按页码保存。
八、总结与扩展到这里,你已经掌握了 Python 提取图像文字的核心技能:从环境配置到单张 / 批量 / PDF 处理,还能解决常见问题。这个方案的优点是开源免费、支持多语言、代码可复用,适合日常办公、数据分析等场景。
如果需要更高级的功能,可以试试这些扩展方向:
结合 OpenCV:做更复杂的预处理,比如图片倾斜矫正、去除水印;调用商业 OCR API:如果 Tesseract 满足不了(比如识别手写体),可以用百度 AI、阿里云的 OCR API,准确率更高;做 GUI 工具:用 PyQt 或 Tkinter 做个界面,让不懂代码的人也能拖放图片识别;批量处理文件夹下的所有 PDF:在 ImageReader 类里加个read_batch_pdfs方法,遍历文件夹里的 PDF 文件。快去试试吧!把代码跑起来,处理你手边的扫描件或截图,省下手动敲字的时间~
经典相传智行盒子