OCR 文字识别实战:让机器读懂图片里的字——检测、识别与结构化

· 约 4 分钟 ·
本文目录(8 节)

OCR(光学字符识别)把图片/扫描件里的文字变成可编辑文本——发票识别、证件录入、截图取字、纸质档案数字化。它是 OpenCV 系列最自然的实战延伸,也是文档智能的入口技术。

前置阅读:OpenCV 图像处理(预处理操作)、PDF 解析(扫描版 PDF 的兜底方案就是它)。

两阶段流水线:先找到字,再认出字

现代 OCR 系统把任务拆成两步,各有专用模型:

文本检测(Detection):找出文字区域的位置——输出每个文本行的四边形框。难点是文字形态多变:横排竖排、弯曲排列、字号悬殊。代表算法 DB(可微分二值化),对弯曲文本友好。

文字识别(Recognition):把每个文本框内的图像切成规范高度后,识别出字符序列。输入是变长图像、输出是变长字符序列,用 CTC 解决对齐问题(和 ASR 里讲的一样)或注意力解码。

方向分类(可选第三步):判断文本框是否旋转了 180°,纠正倒置。

PaddleOCR:中文场景的默认答案

中文 OCR 的开源事实标准是 PaddleOCR:中英文混排效果好、模型小(手机都能跑)、生态完整:

# pip install paddleocr paddlepaddle
from paddleocr import PaddleOCR

ocr = PaddleOCR(use_angle_cls=True, lang="ch")

result = ocr.ocr("invoice.jpg")
for line in result[0]:
    box, (text, conf) = line
    print(f"[{conf:.2f}] {text}   位置: {box}")

输出的 box 是四点坐标,可以画回原图校验,也可以按位置做后续结构化(比如”右上角的数字是金额”)。conf 低于 0.8 的结果建议人工复核——这是发票等严肃场景的常规阈值策略。

预处理:识别率的隐形半壁江山

扫描件/拍照件的质量问题在进模型之前解决:

import cv2

img = cv2.imread("scan.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 去阴影/光照不均:大核背景估计 + 除法归一
bg = cv2.medianBlur(gray, 51)
norm = cv2.divide(gray, bg, scale=255)

# 二值化(对噪点多的老文档用自适应阈值)
binary = cv2.adaptiveThreshold(norm, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                               cv2.THRESH_BINARY, 35, 11)

# 纠偏:霍夫直线或 minAreaRect 估算倾角后旋转

常见问题逐个对应:透视变形(拍照歪了)→ 四点透视变换拉正;光照不均 → 背景除法;噪点 → 中值滤波;倾斜 → 纠偏。我在票据项目里的体感:预处理把识别准确率从 88% 拉到 96%,比换任何模型都值。

结构化:从”一堆字”到”有用的数据”

识别出金额字符串,不等于已经知道它是合计、税额还是单价。结构化需要结合位置、字段名和格式约束,并保留原文与坐标供核对。低置信或金额关系不一致时,应转入复核,而不是用一个看似合理的值补齐。

OCR 输出是”文本 + 位置”的列表,业务要的是字段(发票号码、金额、日期)。结构化三条路:

  1. 规则 + 坐标:版式固定(同一种发票/证件)时,按坐标区域 + 正则提取。简单可靠,版式一变就废。
  2. 关键词锚点:找”金额:“字样,取其右侧/下方的文本。比纯坐标抗版式变化。
  3. 版面分析 + KIE 模型:PaddleOCR 的 PP-Structure 做版面恢复(表格识别成结构化单元格),LayoutXLM 类模型直接做关键信息抽取(KIE)——复杂版式(表格、多栏)的正解。

实践中按版式复杂度递增选择:固定版式走规则,半固定走锚点,自由版式上 KIE 模型。

工程化:批量处理管道

档案数字化这类批量场景,套用平台通用的管道纪律(AI 自动化):每页一个任务、结果按页落盘(JSON:文本+坐标+置信度)、失败页隔离重试、低置信页自动进入人工复核队列。GPU 批处理时 detection 和 recognition 分开组批,吞吐比逐页串行高数倍。

踩坑排查

症状原因处理
识别结果顺序乱按检测顺序输出未排序按坐标”从上到下、从左到右”重排
中文标点全丢模型字典不含标点检查字典配置或后处理补全
表格变成一坨文本缺版面分析上 PP-Structure 表格识别
手写字识别差模型是印刷体训练的换手写专用模型或扩大训练集
竖排文本漏检检测模型不适配旋转 90° 再识别/换支持竖排的模型
小字模糊识别错原图分辨率不足超分预处理或换高清源

练习

  1. 用 PaddleOCR 识别一张发票,画出检测框并输出置信度最低的 5 处。
  2. 对一张光照不均的拍照文档做背景除法预处理,对比前后识别率。
  3. 用锚点法从识别结果中提取”发票号码”和”金额”字段。
  4. 用 PP-Structure 识别一张含表格的页面,导出结构化单元格。

面试常问

Q:OCR 为什么要拆成检测 + 识别两步? 整页直接识别的话序列太长且含大量空白,两步解耦让每个子问题更简单:检测专注定位(对形态鲁棒),识别专注小图内的序列解码。这也是流水线可替换性的来源——检测或识别模型可独立升级。

Q:CTC 在 OCR 里解决什么? 识别输入是变长图像特征序列、输出是变长字符序列,两者没有对应对齐关系。CTC 通过空白符和对所有可能路径求和,免对齐训练序列模型——和语音识别里的作用相同。

Q:扫描件和拍照件的 OCR 难点差异? 扫描件:噪点、泛黄、装订弯曲——靠预处理清洗;拍照件:透视变形、光照不均、模糊——需要几何矫正和光照归一。两者的共同解都是”进模型前的预处理管道”。

Q:识别结果怎么做结构化抽取? 按版式复杂度:固定版式用坐标规则,半固定用关键词锚点 + 相对位置,自由版式用 KIE 模型(LayoutXLM 系,联合文本与版面布局编码)。表格场景用专用的表格结构识别模型。


相关阅读:OpenCV 实战项目、PDF 解析(扫描版 PDF 的 OCR 支线)。

💬 评论

这套方案在哪一步卡住了?也欢迎补充你的实现方式或踩坑经验。

正在连接评论服务,首次访问可能需要几秒…