
平时工作里是不是经常遇到这种麻烦:别人发的扫描件 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 用户需要先装「Homebrew」(如果没装过),打开终端,复制下面的命令回车:
# 装Homebrew(如果没装)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"装完 Homebrew,再装 Tesseract 和多语言包:
# 装Tesseract核心
brew install tesseract
# 装所有语言包(包括英语、俄语、中文等,一步到位)
brew install tesseract-lang装完后,终端输tesseract -v,能看到版本号就说明成了。
tesseract-ocr-w64-setup-5.3.3.20231005.exe)。tesseract -v,能看到版本号就成。如果没勾 Add to PATH,手动配环境变量:
C:Program FilesTesseract-OCR)粘贴进去→一路点 “确定”。打开终端 / CMD,输下面的命令,装 3 个库:
pip install pytesseract pillow pdf2imagepdf2image 库需要 Poppler 才能工作,继续按系统装:
系统 | 安装方法 |
|---|---|
Mac | 终端输 |
Windows |
|
打开 Python 终端(或 IDE 里新建个.py 文件),跑下面的代码:
from PIL import Image
import pytesseract
# 随便找张有英文的图片,替换成你的图片路径
img_path = "test_en.png"
# 打开图片并识别(默认英语)
text = pytesseract.image_to_string(Image.open(img_path), lang="eng")
print(text)如果能打印出图片里的英文,说明环境没问题!如果报错,回头查前面的步骤(尤其是环境变量)。
先从简单的单张图片入手,学会基础用法,再进阶批量处理。
代码超简单,注释写得很清楚:
# 导入需要的库
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,和代码放同一文件夹;要识别其他语言,得先确认 “语言代码”,再装对应语言包(Mac 之前装了tesseract-lang,Windows 要手动下)。
记不住没关系,收藏这个表:
语言 | Tesseract 语言代码 | 说明 |
|---|---|---|
英语 | eng | 默认自带,不用额外装 |
简体中文 | chi_sim | 需要装语言包 |
俄语 | rus | 需要装语言包 |
日语 | jpn | 需要装语言包 |
法语 | fra | 需要装语言包 |
德语 | deu | 需要装语言包 |
rus.traineddata;tessdata目录(比如C:Program FilesTesseract-OCRtessdata)。比如识别一张既有英语又有俄语的图片:
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)运行后,就能同时提取出英语和俄语文字了。
写代码不能每次都复制粘贴,我们把识别逻辑封装成一个类,以后用的时候直接调用,支持单张、批量、PDF 处理,还能配置语言和保存结果。
这个类的代码直接能跑,注释写得很详细,你只需要改路径就行:
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_result把上面的类代码保存为ocr_tool.py,然后新建一个main.py,写调用代码:
# 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文件夹里找到保存的文本文件。有时候识别结果会有乱码或错字,主要是图片质量问题,试试这些优化方法:
我们的类里已经有 “灰度化 + 二值化”,但可以根据图片调整参数:
_preprocess_image里的threshold改小(比如 100);如果偏亮,改大(比如 150)。filter: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_imgdpi设高,比如dpi=600(但会变慢,300 足够日常用)。比如识别中文,用chi_sim(简体)而不是chi_tra(繁体);识别俄语用rus,别用其他相近语言的代码。
这部分是重点!新手最容易踩这些坑,收藏好:
常见错误 / 问题 | 可能原因 | 解决方法 |
|---|---|---|
TesseractNotFoundError |
|
|
PopplerNotInstalledError | 没装 Poppler 或没配环境变量 |
|
多语言识别没效果(全是英语) |
|
|
识别结果是乱码 / 空白 |
|
|
打开图片报错 “cannot identify image file” | 图片损坏或格式不支持 |
|
环境变量配置后还是报错 | 没重启 IDE 或终端 | 环境变量修改后,必须重启 PyCharm、VS Code 等 IDE,或者重启 CMD,不然不生效 |
如果面试时被问到相关问题,这么回答,显得你有实战经验:
回答:做过。核心用的是开源的 Tesseract OCR 引擎,Python 这边用 pytesseract 库调用 Tesseract,用 Pillow 处理图片(打开、预处理)。如果要处理 PDF 扫描件,会用 pdf2image 把 PDF 转成图片,这个库需要依赖 Poppler 工具。流程是:先装工具并配置环境,然后预处理图片(灰度化、二值化),再调用 Tesseract 识别,最后输出结果。我还封装过一个 ImageReader 类,支持单张、批量、PDF 处理,方便复用。
回答:首先 Tesseract 默认只有英语包,其他语言需要单独装。Mac 用brew install tesseract-lang就能装所有语言包;Windows 要去 GitHub 的 tessdata 仓库下载对应语言的 traineddata 文件(比如中文是 chi_sim.traineddata),放到 Tesseract 的 tessdata 目录。然后调用时指定 lang 参数,多语言用 + 连接,比如lang='eng+chi_sim',这样就能同时识别英语和中文了。
回答:主要从图片预处理和工具配置入手。比如:1. 图片预处理,把彩色图转灰度图、二值化,减少干扰;2. 提高图片分辨率,比如 PDF 转图片时设 dpi=300;3. 选择精准的语言包,避免用错代码;4. 如果图片有杂点,加高斯模糊降噪;5. 确保 Tesseract 和语言包是最新版本,修复旧版本的 bug。这些方法能解决大部分日常场景的准确率问题。
回答:普通 PDF 是文本型的,能直接复制文字;PDF 扫描件是图像型的,本质是把图片打包成 PDF,不能直接读文字。处理流程是:先用 pdf2image 库把 PDF 的每一页转成图片,这个库需要 Poppler 支持;转图片时设合适的 dpi(比如 300)提高清晰度;然后对每张图片做预处理(灰度化、二值化);再用 pytesseract 识别文字;最后把所有页的结果合并,按页码保存。
到这里,你已经掌握了 Python 提取图像文字的核心技能:从环境配置到单张 / 批量 / PDF 处理,还能解决常见问题。这个方案的优点是开源免费、支持多语言、代码可复用,适合日常办公、数据分析等场景。
如果需要更高级的功能,可以试试这些扩展方向:
read_batch_pdfs方法,遍历文件夹里的 PDF 文件。快去试试吧!把代码跑起来,处理你手边的扫描件或截图,省下手动敲字的时间~
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。