本地 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 看成了 .crJNI 识别成了 小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 封装得太省心了。

架构设计很聪明

它不做选择,而是全都要:

  1. 先布局分析(PP-DocLayoutV3):把页面切成标题、正文、表格、图表、公式、印章等区域,确定阅读顺序
  2. 再 VLM 识别(0.9B 参数):每个区域独立送入小模型,生成对应的 Markdown/LaTeX
  3. 按页面输出结果(脚本已增加自动合并为单文件)

体验出奇地好

两页简历,约 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.2numpy<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→512
base_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→2048
use_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-2ds-ocr2.py):

# A2 + A3(单图模式已应用;PDF 模式未应用)
model.infer(
    ...,
    base_size=768,      # 单图:已优化;PDF 仍为 1024
    image_size=512,     # 单图:已优化;PDF 仍为 768
)

PaddleOCR-VL-1.5scripts/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 包必须隔离。


八、到底该选谁?

折腾完四个方案,我会按这个顺序选:

  1. 只要文字、要极快:PP-OCRv4。它适合批量扒文本,但别指望它理解版面。
  2. 要 Markdown,还要提取 PDF 内嵌图片:DeepSeek-OCR-2 的 HF 路径。慢,但图片提取能力是它的优势。
  3. 想少折腾环境,只要文本结构化:Ollama deepseek-ocr。它牺牲了图片提取,换来部署简单。
  4. 处理论文、报告、扫描书这类复杂文档: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 版权协议,转载请附上原文链接和本声明。

标签: NVIDIA, PaddleOCR, paddlepaddle, Windows, Markdown, DeepSeek-OCR, HuggingFace, ollama

🎓 呈言英语 智能英语学习平台
📚单词学习 🎧听说练习 📖阅读理解 ✏️拼写练习 🌟 AI智能推荐 · 科学记忆曲线
🚀 立即开始免费学习

添加新评论