多模态 OCR(Vision Language Model OCR)
用视觉语言大模型直接"看图识字",不只提取字符,还能理解文档结构和语义。
从模板匹配到深度学习,传统 OCR 的核心流水线与三大主流工具的原理拆解
内容摘要
OCR(Optical Character Recognition,光学字符识别)是一种将图像中的文字自动转换为可编辑、可搜索的数字文本的技术。简单理解:它给机器装了一双"读字的眼睛",让程序能从截图、扫描件、照片里把文字"读"出来。
OCR(Optical Character Recognition,光学字符识别)是一种将图像中的文字自动转换为可编辑、可搜索的数字文本的技术。简单理解:它给机器装了一双"读字的眼睛",让程序能从截图、扫描件、照片里把文字"读"出来。
OCR 出现的根本原因是:现实世界中大量信息以图像形式存在(纸质文档扫描件、手机拍照、屏幕截图),这些信息对计算机来说就是一堆像素点,无法直接搜索、编辑或被下游 AI 系统使用。OCR 就是打通"视觉像素"到"结构化文本"这条通路的关键技术。
这里所说的"传统 OCR"是相对于多模态大模型 OCR(如 GPT-4V、Qwen-VL)而言的。传统 OCR 采用"流水线"架构——把任务拆成检测、识别、后处理等独立阶段,每个阶段用专门的模型处理。这种模块化设计的优点是每个环节可独立优化和替换,缺点是上游错误会逐级传导到下游。
传统 OCR 的工作流程是一条典型的流水线(Pipeline),由以下阶段串联而成:
| 阶段 | 核心任务 | 输入 / 输出 | 关键技术 |
|---|---|---|---|
| 预处理 | 提升图像质量,为后续阶段做准备 | 原始图像 → 标准化图像 | 灰度化、二值化、去噪、倾斜矫正 |
| 文字检测 | 找到图中所有文字的位置 | 标准化图像 → 文字区域坐标 | DBNet、CRAFT、EAST |
| 文字识别 | 把每个文字区域里的像素转成字符 | 文字区域图像 → 文本字符串 | CRNN + CTC、SVTR |
| 后处理 | 纠错、排版还原 | 原始识别结果 → 最终输出 | 语言模型纠错、排序重组 |
原始图像质量参差不齐——可能是手机拍的歪斜照片、模糊的扫描件、带水印的截图。预处理的目标是把这些"脏数据"清理干净,让后续模型更容易识别。主要操作包括:
预处理看似简单,但对最终精度的影响可达 10%-20%。很多识别不准的问题,根源不在识别模型,而在预处理没做好。
检测阶段的任务是回答"文字在哪里"——在图像中定位所有包含文字的区域,输出每个区域的边界框坐标。
早期方法(如 Tesseract 的传统模式)使用连通域分析和投影直方图来切分文字行和单词。现代方法则使用深度学习模型:
检测精度是整条流水线的瓶颈——如果漏检或框错了区域,后面的识别模型再好也无济于事。
识别阶段回答"写的是什么"——把检测到的每个文字区域图像转换为字符序列。这是整个 OCR 流水线技术含量最高的环节。
主流识别架构是 CRNN + CTC:
更新的架构如 SVTR(Spatial Visual Transformer)用 Transformer 替代 LSTM,能捕获更长距离的上下文关系,PaddleOCR v3+ 已将其作为默认识别器。
识别模型的原始输出往往不够完美——可能有重复字符、错误拼写、排列顺序混乱。后处理阶段负责"收尾":
传统 OCR 的核心技术难点集中在识别阶段。以目前最主流的 CRNN + CTC 架构为例,其工作过程如下:
第一步:特征提取(CNN)
输入是一张裁剪好的文字区域图像(例如 32 x 200 像素的一行文字)。卷积网络将其编码为一组特征向量序列。具体来说,CNN 在水平方向上把图像切成若干列,每一列生成一个特征向量,描述该位置的视觉信息。假设图像宽度对应 T 个时间步,则输出为 T 个特征向量。
第二步:序列建模(Bi-LSTM)
双向 LSTM 在 T 个特征向量上前后各扫一遍,融合每个位置的左侧和右侧上下文信息。这一步的目的是让模型在识别某个位置时,能同时参考前后邻居的特征——比如识别一个模糊的字母时,结合前后字符可以大幅提高准确率。
第三步:CTC 解码
CTC 层将 Bi-LSTM 的输出映射到最终的字符序列。CTC 的核心思想是引入一个"空白符号(blank)",允许模型在不确定字符边界的情况下输出重复字符和空白符号,然后通过去重和去空白操作得到最终文本。例如:
原始输出序列:h-ee-ll-ll-oo(其中 - 表示 blank)
→ 去 blank:heelllloo
→ 去重复:hello
这种设计的精妙之处在于:模型不需要预先知道每个字符在图像中占几个像素、从哪里开始到哪里结束,CTC 自动学习字符与图像位置的对齐关系。
图中从顶部到底部展示了完整的 OCR 流水线。虚线框标注的"CNN → Bi-LSTM → CTC"三段组成了 CRNN 识别模型的内部结构,是整条流水线的技术核心。预处理和后处理虽然看起来简单,但对最终效果的影响不可忽视。
三大主流 OCR 工具在流水线各阶段的技术选型不同:
| 对比维度 | Tesseract | PaddleOCR | EasyOCR |
|---|---|---|---|
| 检测方法 | 传统连通域分析 + 投影 | DBNet(深度学习) | CRAFT(深度学习) |
| 识别方法 | LSTM(v4+ 升级) | SVTR / CRNN(可切换) | CRNN(CNN + LSTM + CTC) |
| 硬件偏好 | CPU 优先 | GPU 推荐(有轻量 CPU 模型) | GPU 推荐 |
| 语言支持 | 116+ 种 | 100+ 种 | 80+ 种 |
| 模型体积 | 中等 | 极轻量(< 10MB 可选) | 较大 |
| 适用场景 | 清晰印刷体文档 | 复杂版面、多语言、生产级部署 | 快速原型、简单集成 |
| 维护方 | Google 赞助 | 百度 PaddlePaddle | 社区驱动 |
以下伪代码展示 CRNN + CTC 的核心机制,帮助理解识别阶段的数据流向:
# 伪代码:CRNN + CTC 识别流程
# 基于 PyTorch 风格,仅用于说明原理,不可直接运行
import torch
import torch.nn as nn
class CRNN(nn.Module):
"""CRNN 识别模型的核心结构"""
def __init__(self, num_classes):
super().__init__()
# 第一部分:CNN 特征提取
# 将图像(H=32, W=变长)编码为特征序列
self.cnn = nn.Sequential(
nn.Conv2d(1, 64, 3, padding=1), # 灰度图输入
nn.ReLU(),
nn.MaxPool2d(2, 2), # 尺寸减半
nn.Conv2d(64, 128, 3, padding=1),
nn.ReLU(),
nn.MaxPool2d(2, 2), # 再减半
# ...更多卷积层
)
# 第二部分:Bi-LSTM 序列建模
# 在水平方向上建模字符间的依赖关系
self.rnn = nn.LSTM(
input_size=128 * 8, # CNN 输出展平后的维度
hidden_size=256,
num_layers=2,
bidirectional=True, # 双向 LSTM:同时看左和看右
)
# 第三部分:全连接层 → CTC 解码
# 输出每个时间步的字符概率分布
self.fc = nn.Linear(256 * 2, num_classes) # 双向所以 x2
def forward(self, image):
# CNN 提取特征:(B, 1, 32, W) → (B, 128, 8, W/4)
features = self.cnn(image)
# 将特征图按列切分为序列:(W/4, B, 128*8)
b, c, h, w = features.size()
features = features.view(b, c * h, w).permute(2, 0, 1)
# Bi-LSTM 序列建模:(W/4, B, 512)
output, _ = self.rnn(features)
# 全连接层输出字符概率:(W/4, B, num_classes)
logits = self.fc(output)
return logits # 送入 CTC Loss 训练,或 CTC Decoder 推理
上述代码对应三个核心组件:self.cnn 对应特征提取,self.rnn 对应序列建模,self.fc + CTC 对应解码输出。训练时使用 torch.nn.CTCLoss,推理时使用贪心解码或 beam search 解码。
| 概念 | 与传统 OCR 的区别 | 更适合关注的重点 |
|---|---|---|
| 多模态大模型 OCR | 使用 VLM(如 GPT-4V、Qwen-VL)端到端理解图像,不拆检测/识别阶段 | 语义理解、复杂版面、零样本泛化 |
| 文档智能(Document AI) | OCR 是文档智能的第一步,文档智能还包括版面分析、表格提取、信息抽取等 | 结构化提取、端到端文档处理 |
| 计算机视觉(CV) | OCR 是 CV 的一个子领域,CV 还包括目标检测、图像分类、语义分割等 | 广义图像理解 |
| STR(场景文字识别) | OCR 偏向文档扫描件,STR 专注自然场景中的文字(路牌、店招等),难度更高 | 不规则文字、复杂背景、透视变形 |
核心区别:
| 常见误区 | 正确理解 |
|---|---|
| OCR 识别精度能达到 100% | OCR 是概率性的,即使最好的模型在干净文档上也只有 95-99% 的准确率。图像质量、字体、背景都会影响结果,生产环境必须配合置信度过滤和人工审核 |
| Tesseract 已经过时不能用 | Tesseract 5.x 引入了 LSTM 神经网络,在清晰印刷体上依然表现稳定。它的优势是纯 CPU 运行、无需 GPU、部署简单,在预算有限或硬件受限的场景下仍是首选 |
| 选一个 OCR 工具就够了 | 不同工具有不同的优势场景。生产系统中常见的做法是:先用 PaddleOCR 做主力识别,对置信度低的结果用 Tesseract 交叉验证,最后用 EasyOCR 处理特殊语言——多工具组合互补 |
| OCR 输出可以直接作为最终数据 | OCR 结果必须经过验证和清洗,特别是在金融、法律等领域。常见问题包括:数字 0 和字母 O 混淆、中文同形字误识别、标点符号丢失等 |
参考答案:
CNN 负责从图像中提取视觉特征(笔画形状、空间位置),解决"看到了什么"的问题。RNN(Bi-LSTM)负责建模字符间的序列依赖关系,解决"前后字符如何关联"的问题——比如看到"qu"后推断下一个字符大概率是元音。CTC 负责将连续的帧级预测对齐到离散的字符序列,解决"不知道每个字符在图像中具体占多宽"的对齐难题。去掉 CNN,模型看不到图像内容;去掉 RNN,模型无法利用上下文;去掉 CTC,模型无法处理变长序列的对齐。
参考答案:
Tesseract 通过 lang 参数指定语言包组合,如 lang='chi_sim+eng'(简体中文 + 英文),数字包含在英文语言包中。PaddleOCR 设置 lang='ch'(中文模式默认同时支持英文和数字),也可用 ['ch', 'en'] 多语言组合。EasyOCR 在初始化 Reader 时传入语言列表 ['ch_sim', 'en']。三个工具中,PaddleOCR 的中文识别精度最高(因为百度在中文语料上的训练投入最大),Tesseract 的中文支持相对较弱(需要额外下载中文语言包),EasyOCR 介于两者之间。
参考答案:
推荐流水线设计:(1) 预处理阶段用 OpenCV 做灰度化、自适应二值化、倾斜矫正,确保扫描件质量统一;(2) 主识别用 PaddleOCR(PP-OCRv5),因为其在复杂中文文档上的准确率最高;(3) 对置信度低于 0.9 的文字区域,用 Tesseract 5.x 做交叉验证,两者结果一致则采用,不一致则标记为"需人工审核";(4) 后处理阶段用语言模型(如规则引擎或 LLM)做合同专业术语纠错;(5) 关键字段(当事人名称、金额、日期)通过正则表达式提取后,再做一轮格式校验。容错重点在两个环节:识别阶段的双引擎交叉验证,以及关键字段的规则校验。这种设计在清晰扫描件上通常能达到 98%+ 的准确率。
优先展示同分类且标签更接近的内容,方便继续串联学习。
用视觉语言大模型直接"看图识字",不只提取字符,还能理解文档结构和语义。
开源 PDF 文档解析工具,将复杂 PDF 转换为 Markdown/JSON,适合 RAG 系统的文档预处理。
用于系统化测量 LLM/Agent 系统输出质量与行为可靠性的指标体系和方法论