本地 OCR 到 VLM:四个 PDF 识别方案实测
本地 OCR 到 VLM:四个 PDF 识别方案实测
- 本地 OCR 到 VLM:四个 PDF 识别方案实测
本文首发地址 https://h89.cn/archives/596.html
测试设备:NVIDIA RTX 4060 Laptop (8GB) / CUDA 11.8 / Windows 11
一、AI 读不懂 PDF,很多时候不是 AI 的锅
上周我把一份扫描版简历丢给 AI 助手,想让它帮忙整理成结构化数据。结果 AI 一本正经地把邮箱写成了 me@h89.cr。
我愣了一下,低头看原文——明明是 me@h89.cn。这件事让我意识到:传统 OCR 提取出来的文字,AI 根本没法好好理解。
不只是邮箱会认错。英文单词粘在一起变成 OceanDepths,表格变成一团乱麻,公式直接变乱码,最要命的是所有内容平铺成一锅粥,标题和正文完全分不清。
于是我决定动手,在自己的笔记本上搭一套本地 PDF 识别方案。折腾了两天,先后试了 PP-OCRv4、DeepSeek-OCR-2、Ollama deepseek-ocr 和 PaddleOCR-VL-1.5,记录如下。

二、PP-OCRv4:快是真快,坑也是真的多
最先上手的是 PP-OCRv4。毕竟名声在外,中文 OCR 的标杆,而且 paddlepaddle-gpu==2.6.2 + paddleocr==2.7.3 这套组合在 Windows 上有成熟的 GPU 支持。
跑起来之后的惊喜
两页简历,1.4 秒 就跑完了。十页设计素材,1.9 秒。这速度放在本地跑,基本就是眨眼的事。显存也只吃了 2GB 左右,RTX 4060 的 8GB 显存表示毫无压力。
但结果让我哭笑不得
输出的是纯文本,所有内容像流水账一样平铺。更尴尬的是前面说的那个邮箱——它把 .cn 看成了 .cr,JNI 识别成了 小ni。
设计素材那页更惨。本来是四个色块配颜色名,结果被它拼成了一行:Deep NavyTealSeafoamCream,连空格都没剩下。AI 拿到这份"战果",估计会以为这是什么新型编程语言。
另外它完全不管版面。标题、正文、页眉、页码全部混在一块,表格直接变文本,图片被忽略,公式变成天书。
代码写得我头大
为了把 OCR 结果转成能看的 Markdown,我手写了快 200 行代码:手动按坐标行分组、处理文本框顺序、拼接段落……一顿操作下来,最多只能说"能跑"。
PP-OCRv4 给我的感觉,就像一个语速极快但有点近视的速记员。

三、DeepSeek-OCR-2:让 VLM 来收拾残局
既然传统 OCR 搞不定语义理解,那就上 VLM(视觉语言模型)。
DeepSeek-OCR-2 走的是另一条路:把 PDF 每页转成图片,直接丢给多模态大模型,让它自己"看"、自己"理解"、自己输出 Markdown。
效果确实好了
同样是那份简历,邮箱终于认对了,JNI 也回来了。更惊喜的是它自动给内容加了 Markdown 结构:## 陈天真、## 个人优势、## 工作经历,层次分明。还顺手把简历里嵌入的头像图片也提取了出来,在 Markdown 里保留了引用路径。
这感觉像是换了一个会思考的实习生,不再是机械抄写,而是真正在读这份简历。
但速度让我回到了拨号上网时代
两页简历,跑了 约 116 秒。十页设计素材,约 146 秒。
问题出在它的 vLLM 加速路径在 Windows 上编译失败,只能用 HuggingFace Transformers 路径,逐页串行处理,没有异步队列。RTX 4060 的 8GB 显存被吃掉 6.4GB,基本满载。
DeepSeek-OCR-2 就像一个读得很认真但看得极慢的学霸。
同模型换后端:Ollama
既然 HF Transformers 路径慢,vLLM 又装不上,那同一份模型换个后端行不行?
我把 DeepSeek-OCR-2 转成了 GGUF 格式,用 Ollama 跑:ollama run deepseek-ocr。
结果意外:比 HF 路径快了约 10%。两页简历 105.7 秒,十页素材 142.2 秒。每页生成 token 的速度约 15-20 tok/s,和输出长度强相关——简历每页 1000+ tokens 要花 50 秒,设计素材每页 200 tokens 只要 14 秒。
但代价是丢了图片提取能力。HF 路径的 save_results=True 能把 PDF 内嵌图片扒到本地,Ollama 只返回纯文本,图片块只剩一个空引用。
Ollama 就像给学霸配了辆电动车——比走路快,但后备箱被人拆了。
四、PaddleOCR-VL-1.5:两手都要抓
折腾到 PaddleOCR-VL-1.5 时,我其实有点累了。但它给了我一个惊喜:pipeline 封装得太省心了。
架构设计很聪明
它不做选择,而是全都要:
- 先布局分析(PP-DocLayoutV3):把页面切成标题、正文、表格、图表、公式、印章等区域,确定阅读顺序
- 再 VLM 识别(0.9B 参数):每个区域独立送入小模型,生成对应的 Markdown/LaTeX
- 按页面输出结果(脚本已增加自动合并为单文件)
体验出奇地好
两页简历,约 112 秒。十页素材,约 225 秒。后面我又做了优化(降低分辨率 + 缩短 token + 关闭印章识别),速度才反超 DeepSeek-OCR-2。
更关键的是它原生支持我前面遇到的所有痛点:
- 公式输出 LaTeX
- 表格输出 Markdown 表格格式
- 图表自动识别并描述
- 印章也能认
- 跨页表格处理(依赖版面分析,未实测验证)
- 不规则文字(倾斜、弯曲)照样检测
代码量也降到了 50 行,pipeline 一行调用:pipeline.predict(pdf),完事。
另外 paddlepaddle-gpu==3.2.1 是 Paddle 首个支持 Windows GPU 的 3.x 版本,终于不用再被 protobuf==3.20.2 和 numpy<2.0 绑架了。
PaddleOCR-VL-1.5 给我的感觉,像一个经验丰富、手脚麻利的资深助理。
五、实测数据一图看清
| 维度 | PP-OCRv4 | DeepSeek-OCR-2 (HF) | Ollama deepseek-ocr | PaddleOCR-VL-1.5 |
|---|---|---|---|---|
| 速度(2页简历) | 1.4s | ~116s | ~106s | ~112s |
| 速度(10页素材) | 1.9s | ~146s | ~142s | ~225s |
| 显存占用 | ~2 GB | ~6.4 GB | ~6.4 GB | ~5 GB |
| 邮箱识别 | h89.cr ❌ |
h89.cn ✅ |
h89.cn ✅ |
h89.cn ✅ |
| 英文术语 | 小ni ❌ |
JNI ✅ |
JNI ✅ |
JNI ✅ |
| Markdown 结构 | 无 | 有 | 有 | 有 |
| 公式/表格/图表 | ❌ | ✅ | ✅ | ✅ |
| 提取内嵌图片 | ❌ | ✅ | ❌ | ❌ |
| 部署代码量 | ~200 行 | ~230 行 | ~10 行 | ~50 行 |
⚠️ 受系统环境、驱动版本、GPU 温度、模型缓存状态等运行时差异影响,以下测试结果仅供参考,不代表绝对性能排序。
一个有意思的发现:PP-OCRv4 的速度优势在复杂页面上会消失。测试了一份超大页面(4768x10761)的 PDF,它跑了 38 秒,因为默认检测边长限制 2048,大页面需要分割处理。
六、优化验证:速度提升后,质量有没有垮?
⚠️ 以下所有测试均在 单张 NVIDIA RTX 4060 Laptop (8GB) 上完成,无多 GPU、无分布式、无 vLLM 加速。
下面是两个 VLM 方案的优化前后耗时对比,以及一个关键问题的答案:快了之后,识别结果会不会变差?
优化前后耗时对比
| 方案 | 场景 | 默认参数 | 优化手段 | 优化后 | 效果 |
|---|---|---|---|---|---|
| DeepSeek-OCR-2 | 2页简历 | ~116s | image_size=768→512base_size=1024→768 |
~69s | ↓40% |
| DeepSeek-OCR-2 | 10页素材 | ~146s | 同上 | ~186s | ↑27%(反效果) |
| PaddleOCR-VL-1.5 | 2页简历 | ~112s | max_pixels=1024²→768²max_new_tokens=4096→2048use_seal_recognition=True→False |
~83s | ↓26% |
| PaddleOCR-VL-1.5 | 10页素材 | ~225s | 同上 | ~112s | ↓50% |
关键结论:
- DeepSeek-OCR-2 降低分辨率对文字密集型文档(简历)加速明显(↓40%),但对设计素材反而拖慢(↑27%),不建议盲目统一降低 PDF 模式的参数。
- PaddleOCR-VL-1.5 的降分辨率 + 缩短 token 对两类文档都有显著收益,10页素材提升最明显。
DeepSeek-OCR-2 这个反效果挺反直觉。我后来对比输出长度和单页耗时,猜测原因不在"像素少了所以一定更快",而在 PDF 模式的耗时主要受生成 token 数和页面切分路径影响。
简历是文字密集型页面,降低分辨率后视觉编码压力下降,但结构和输出长度基本没变,所以直接加速。设计素材每页文字少,本来视觉编码和生成都不重,降分辨率后反而可能让模型更难判断色块边界、标题层级和阅读顺序,生成过程更犹豫,单页耗时被拉长。也就是说,VLM OCR 的优化不能只看图片尺寸,还要看页面类型和输出 token。
质量验证:
diff -u逐字对比优化前后输出,DeepSeek-OCR-2 与 PaddleOCR-VL-1.5 均 零质量损失,邮箱、英文术语、标题层级、长文本均无差异。
代码改动记录
DeepSeek-OCR-2(ds-ocr2.py):
# A2 + A3(单图模式已应用;PDF 模式未应用)
model.infer(
...,
base_size=768, # 单图:已优化;PDF 仍为 1024
image_size=512, # 单图:已优化;PDF 仍为 768
)
PaddleOCR-VL-1.5(scripts/ocr_vl.py):
# B1 + B2 + B4
pipeline = PaddleOCRVL(
...,
use_seal_recognition=False, # 原 True
)
output = pipeline.predict(
pdf_path,
max_pixels=768 * 768, # 原 1024*1024
max_new_tokens=2048, # 原 4096
)
七、那些让我想摔键盘的坑
PP-OCRv4 的五连坑
1. cuDNN 的隐藏依赖
报错 cudnn64_8.dll not found (error code 126)。排查半天发现,cudnn_cnn_infer64_8.dll 依赖 zlibwapi.dll,而 cuDNN 安装包居然没带这个文件。最后从 PyTorch 包里偷了一个放到项目目录,通过 PATH 加载。最坑的是 os.add_dll_directory() 对 Paddle 完全无效,必须用环境变量。
2. CUDA 版本对不上
系统装的是 CUDA 12.8,但 paddlepaddle-gpu==2.6.2 是 CUDA 11.8 编译的。驱动虽然能向下兼容,但运行时库不匹配,报 cublasLt64_11.dll 缺失。最后只能两个 CUDA 版本共存,Paddle 走 11.8 的路径。
3. PaddlePaddle 3.x 没有 Windows GPU
试着手贱升级,结果 PyPI 上 paddlepaddle-gpu 最高只有 2.6.2。官方 CUDA 12 的 wheel 也一样。结论:Windows 用户在此之前被 2.x 锁死了。
4. NumPy 和 protobuf 的版本牢笼
numpy必须<2.0,装 2.x 直接 ABI 报错protobuf必须精确等于3.20.2,多一个小版本都报Descriptors cannot be created directly- 安装时得
--force-reinstall硬降级,满屏红色警告看得人心惊肉跳
5. API 格式突变
paddleocr==2.7.3 返回 list,3.5.0+ 返回 dict。我代码刚按 list 写好,一升级直接 AttributeError。最后只能写兼容逻辑,两边都判断。
DeepSeek-OCR-2 的坑
vLLM 在 Windows 上是个谎言
官方说支持 vLLM 加速,我兴冲冲装完 vllm==0.8.5,结果运行时报 vllm._C 模块未构建——这玩意在 Windows 上需要从源码编译 C++ 扩展,编译失败。最终只能用 HuggingFace Transformers,速度差了好几倍。
Ollama 的坑
GGUF 转换不是所有模型都能转
DeepSeek-OCR-2 的 vision 模块用了自定义的 image processor,转 GGUF 时差点翻车。Ollama 对 deepseekocr 这个 family 的支持属于"刚好能用"——能跑,但比标准 Llama 模型麻烦。
图片提取凭空消失
这是最大的坑。HF 路径的 save_results=True 会把 PDF 里内嵌的图片写到本地,Ollama 只返回文本,图片块只剩一个 <|ref|>image<|/ref|> 的空壳。如果你需要提取图片,Ollama 这条路走不通。
PaddleOCR-VL-1.5 的坑
1. 模型下载是个大关
首次运行要联网下载 2-3GB 模型。我在公司跑得好好的,回家想离线用,傻眼了。后来学乖了,先把 .paddlex/official_models/ 整个复制走。
2. 显存不是无限的
8GB 看起来多,但大 PDF(50页+)照样 OOM。不过好在可以 --device cpu 降级,就是速度慢 5-10 倍,至少能跑完。
3. 2.x 和 3.x 不能混用
PP-OCRv4 和 VL-1.5 必须各用各的虚拟环境。我一开始图省事共用 venv,结果 ABI 不兼容,报错信息看得我一头雾水。模型缓存可以共用 ~/.paddlex/,但 Python 包必须隔离。
八、到底该选谁?
折腾完四个方案,我会按这个顺序选:
- 只要文字、要极快:PP-OCRv4。它适合批量扒文本,但别指望它理解版面。
- 要 Markdown,还要提取 PDF 内嵌图片:DeepSeek-OCR-2 的 HF 路径。慢,但图片提取能力是它的优势。
- 想少折腾环境,只要文本结构化:Ollama deepseek-ocr。它牺牲了图片提取,换来部署简单。
- 处理论文、报告、扫描书这类复杂文档:PaddleOCR-VL-1.5。公式、表格、图表、版面顺序这些能力更完整,也是我最后会长期保留的方案。
九、写在最后
PP-OCRv4 快但糙,DeepSeek-OCR-2 好但慢,Ollama 是轻量妥协,PaddleOCR-VL-1.5 在速度、功能和代码量上更均衡。如果只是偶尔转一两页 PDF,PP-OCRv4 完全够用;但如果要让 AI 真正"读懂"一份复杂文档,我会优先用 PaddleOCR-VL-1.5。
另外 Windows 本地跑深度学习真是个修行过程。CUDA 版本、DLL 缺失、Python 包冲突……每一步都可能踩坑。好在这四个方案我都已经调通了,配置好的环境就在各自的目录里,下次重装系统不至于从头再来。
希望这篇记录能帮你少走点弯路。
附:文中所有测试数据均来自同一台笔记本的实测,受系统环境、驱动版本、GPU 温度、模型缓存状态等运行时差异影响,结果仅供参考,不同硬件环境表现可能有显著差异。
本文链接:本地 OCR 到 VLM:四个 PDF 识别方案实测 - https://h89.cn/archives/596.html
版权声明:原创文章 遵循 CC 4.0 BY-SA 版权协议,转载请附上原文链接和本声明。