手把手教你用Python搞定凭证档案数字化与OCR识别
一、开发环境与依赖库搭建
在开始编写代码之前,必须先配置好Python运行环境。本文基于Python 3.8版本开发,兼容Python 3.9及3.10。请勿使用低于3.8的版本,以免依赖库不兼容。
安装PaddlePaddle深度学习框架。这是运行OCR引擎的基础。请根据你的操作系统选择对应的安装命令。如果你是Windows用户且没有NVIDIA显卡,请执行以下命令安装CPU版本:
python -m pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple
如果你是Linux用户或拥有NVIDIA GPU并配置了CUDA环境,请执行GPU版本安装命令以获得更快的处理速度:
python -m pip install paddlepaddle-gpu -i https://mirror.baidu.com/pypi/simple
接下来,安装OCR核心库及其他必要的图像处理依赖库。打开终端或命令行窗口,一次性执行以下命令:
pip install paddleocr opencv-python pillow pdf2image numpy
注意:pdf2image依赖Poppler工具。如果你在Windows上运行,必须下载Poppler并配置环境变量,或者将其bin目录路径添加到系统PATH中。Mac用户可以通过brew install poppler直接安装,Ubuntu用户通过sudo apt-get install poppler-utils安装。
二、PDF凭证批量转图像处理
档案数字化的一大痛点是处理PDF格式的电子凭证。我们需要先将PDF转换为高分辨率的图像,以便后续进行OCR识别。这一步对于保证识别率至关重要,直接处理PDF文件会导致识别失败。
新建一个名为digitization.py的文件。首先编写PDF转换函数。为了保证清晰度,我们将DPI设置为300,这是档案级数字化的最低标准。
from pdf2image import convert_from_path
import cv2
import numpy as np
import os
def pdf_to_images(pdf_path, output_folder):
"""
将PDF文件转换为图像列表并保存
:param pdf_path: PDF文件路径
:param output_folder: 输出图片的文件夹
:return: 生成的图片路径列表
"""
if not os.path.exists(output_folder):
os.makedirs(output_folder)
使用300 DPI进行转换,保证文字清晰度
images = convert_from_path(pdf_path, dpi=300)
image_paths = []
for i, image in enumerate(images):
将PIL图像转换为OpenCV格式
opencv_img = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
img_name = f"page_{i+1}.png"
img_path = os.path.join(output_folder, img_name)
cv2.imwrite(img_path, opencv_img)
image_paths.append(img_path)
return image_paths
三、图像预处理与倾斜校正
扫描或拍摄的凭证往往存在噪点、光照不均或倾斜问题。直接识别倾斜的图片会导致准确率大幅下降。我们需要实现一个自动倾斜校正算法,通过检测文本行来计算旋转角度。
在digitization.py中继续添加以下预处理代码:

def deskew_image(image):
"""
校正图像倾斜角度
"""
转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
二值化处理,使用Otsu算法自动寻找阈值
gray = cv2.bitwise_not(gray)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
检测坐标点,计算最小旋转矩形
coords = np.column_stack(np.where(thresh > 0))
angle = cv2.minAreaRect(coords)[-1]
调整角度
if angle < -45:
angle = -(90 + angle)
else:
angle = -angle
旋转图像
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)
return rotated
四、OCR识别核心逻辑与结构化
这里使用PaddleOCR进行文字识别。它内置了中文检测和识别模型,无需额外下载模型文件,第一次运行时会自动下载。我们将识别结果结构化为JSON格式,包含坐标、文本内容和置信度。
继续添加OCR处理函数:
from paddleocr import PaddleOCR
import json
初始化OCR模型,use_angle_cls=True启用方向分类器,提高识别准确率
ocr = PaddleOCR(use_angle_cls=True, lang="ch")
def process_ocr(image_path):
"""
对单张图片进行OCR识别并返回结构化数据
"""
读取图片
img = cv2.imread(image_path)
执行倾斜校正
img_corrected = deskew_image(img)
执行OCR识别
result = ocr.ocr(img_corrected, cls=True)
structured_data = []
解析结果
if result and result[0]:
for idx in range(len(result[0])):
res = result[0][idx]
res结构: [[左上x,左上y], [右上x,右上y], [右下x,右下y], [左下x,左下y]], (文本, 置信度)
text_info = {
"coordinates": res[0],
"text": res[1][0],
"confidence": float(res[1][1])
}
structured_data.append(text_info)
return structured_data
五、完整落地代码整合
将上述模块整合,编写主函数入口。这个脚本将支持输入一个PDF文件路径,自动完成转换、校正、识别,并最终输出一个包含所有凭证文本信息的JSON文件。
请将以下完整代码复制到你的digitization.py文件中(确保前面的依赖库已安装):
import sys
import cv2
import numpy as np
import os
import json
from pdf2image import convert_from_path
from paddleocr import PaddleOCR
初始化OCR引擎
ocr = PaddleOCR(use_angle_cls=True, lang="ch", show_log=False)
def deskew_image(image):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.bitwise_not(gray)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
coords = np.column_stack(np.where(thresh > 0))
if coords.size == 0:
return image 防止空白图报错
angle = cv2.minAreaRect(coords)[-1]
if angle < -45:
angle = -(90 + angle)
else:
angle = -angle
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)
return rotated
def process_single_file(file_path, output_json):
判断是PDF还是图片
if file_path.lower().endswith('.pdf'):
print(f"正在处理PDF文件: {file_path}")
try:
images = convert_from_path(file_path, dpi=300)
except Exception as e:
print(f"PDF转换失败,请检查Poppler是否安装: {e}")
return
else:
print(f"正在处理图片文件: {file_path}")
img_pil = Image.open(file_path)
images = [img_pil]
all_results = []
for idx, img_pil in enumerate(images):
print(f" - 正在识别第 {idx+1} 页...")
PIL转OpenCV
opencv_img = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)
预处理:倾斜校正
corrected_img = deskew_image(opencv_img)
OCR识别
result = ocr.ocr(corrected_img, cls=True)
page_data = []
if result and result[0]:
for line in result[0]:
text_content = {
"text": line[1][0],
"confidence": float(line[1][1]),
"box": line[0]
}
page_data.append(text_content)
all_results.append({
"page_number": idx + 1,
"content": page_data
})
保存结果
with open(output_json, 'w', encoding='utf-8') as f:
json.dump(all_results, f, ensure_ascii=False, indent=4)
print(f"处理完成!结果已保存至: {output_json}")
if __name__ == "__main__":
使用方法:python digitization.py "你的文件路径"
if len(sys.argv) < 2:
print("使用错误: 请拖入文件到脚本或提供文件路径")
print("示例: python digitization.py C:\\voucher.pdf")
else:
input_file = sys.argv[1]
output_file = os.path.splitext(input_file)[0] + "_result.json"
process_single_file(input_file, output_file)
六、执行操作与结果验证
代码准备就绪后,最后一步是运行并查看效果。准备一份扫描好的凭证PDF文件或图片文件。
1. 打开命令行终端(CMD或PowerShell)。
2. 切换到脚本所在的目录。例如你的脚本在D盘的work文件夹下:
d:
cd work
3. 执行命令。假设你的凭证文件名为invoice.pdf,直接执行:
python digitization.py invoice.pdf
4. 观察终端输出。你会看到“正在处理PDF文件”、“正在识别第1页...”等实时日志。第一次运行时,PaddleOCR会自动下载约10MB的模型文件,请耐心等待。
5. 验证结果。运行结束后,当前目录下会生成invoice_result.json。用文本编辑器打开它,你将看到标准化的JSON数据:
[
{
"page_number": 1,
"content": [
{
"text": "增值税专用发票",
"confidence": 0.9985,
"box": [[...]]
},
{
"text": "金额:¥1200.00",
"confidence": 0.9652,
"box": [[...]]
}
]
}
]
通过上述步骤,你已经完成了一个从PDF文档到结构化JSON数据的全流程数字化系统。这套代码可以直接集成到你的后端服务中,用于财务自动对账或档案检索系统的开发。