用 PySide6 和 PaddleOCR 做一个剪贴板 OCR 小工具
问题重述
日常看论文、网页、截图、PDF 的时候,经常会遇到一个很小但高频的问题:想把截图里的文字 OCR 出来。
通常做法有几种:
- 打开在线 OCR 网站
- 调用系统截图工具
- 用浏览器插件
- 写一个临时脚本
- 直接丢给大模型识别
这些方法都能用,但是都不太适合作为一个“随手工具”。
我的需求比较明确:
- 从剪贴板读取图片
- 本地模型推理
- 支持 GPU
- 支持模型切换
- UI 简单,不做多余功能
- 依赖用
uv/pixi管理 - 尽量少折腾环境
于是做了一个小工具:ppocr-client。
功能目标
- 从剪贴板读取图片
- 在界面中预览图片
- 调用 OCR 模型识别
- 显示文本结果和原始 JSON
模型目前支持两个PaddleOCR系列的模型:
PP-OCRv6(轻量)PaddleOCR-VL-1.6(全能)
默认使用:
PP-OCRv6 + gpu:0
启动后会自动预热模型。预热完成后,实际推理耗时大约在 380ms 左右。(4050 Laptop 6G)
UI 设计

布局上分成左右两块:
- 左侧:剪贴板图片预览
- 右侧:识别结果
右侧再分两个 tab:
- 文本
- 原始 JSON
没有做菜单栏,也没有做复杂设置,目前还不需要,后面功能复杂了再加。顶部放几个必要控件:
模型选择
设备选择
读取剪贴板
识别
复制结果
OCR 后端封装
后端封装PaddleOCR:
class PaddleOcrManager:
def recognize(self, image, model, device):
...
模型 pipeline 会自动缓存:
self._pipelines[(model, device_key)] = pipeline
所以第一次识别会比较慢,后续同一个进程内再次识别会快很多。
自动预热
刚开始测试 GPU 推理时,第一次耗时大约 20s 以上。
后来确认这不是单次 OCR 真正需要这么久,而是包含了:
- PaddleOCR pipeline 初始化
- 模型权重加载
- CUDA context 初始化
- cuDNN / cuBLAS 动态库加载
- GPU predictor 创建
- 第一次 kernel 初始化
所以加了自动预热。
应用启动 250ms 后,在后台用一张小白图跑一次当前模型:
PP-OCRv6 / gpu:0
预热不会覆盖文本框结果,只更新状态栏和耗时标签。切换模型或设备后,也会自动重新预热。
依赖管理
项目用 uv 和 pixi 同时管理。
uv 侧需要注意的是 Paddle GPU 包。
Windows 下 paddlepaddle-gpu 没有 Python 3.13 的 wheel,因此项目约束为:
requires-python = ">=3.12,<3.13"
GPU 版 Paddle 使用 Paddle 官方 CUDA 12.6 源:
[[tool.uv.index]]
name = "paddle-cu126"
url = "https://www.paddlepaddle.org.cn/packages/stable/cu126/"
explicit = true
并固定:
paddlepaddle-gpu==3.3.1
GPU 环境问题
GPU 这块踩了几个坑。
1. CPU 版 PaddlePaddle
一开始环境里装的是:
paddlepaddle==3.3.1
这个是 CPU 版。
选择 gpu:0 后,PaddleX 会进入一些 fallback 路径,最后出现很迷惑的 oneDNN / PIR 报错:
ConvertPirAttribute2RuntimeAttribute not support
后来加了检查:
paddle.is_compiled_with_cuda()
paddle.device.cuda.device_count()
如果当前是 CPU-only PaddlePaddle,直接提示用户安装 GPU 版,而不是继续执行。
2. Python 3.13 没有 GPU wheel
paddlepaddle-gpu 在 Windows 下没有 cp313 wheel。
所以环境切到了 Python 3.12。
3. cuDNN DLL 找不到
装好 GPU 版 Paddle 后,又遇到:
cudnn64_9.dll not configured correctly
最后显式安装了 CUDA / cuDNN runtime wheels,并在应用启动时把这些目录加入 DLL 搜索路径:
.venv/Lib/site-packages/nvidia/*/bin
4. cuDNN 版本警告
一开始装到的是 cuDNN 9.5,Paddle 提示它是按 cuDNN 9.9 编译的。
最后升级到:
nvidia-cudnn-cu12==9.9.0.52
警告消失。
模型缓存
PaddleX 默认缓存目录是:
~/.paddlex
为了符合项目习惯,改成了:
~/.kozbox/ppocr-client/
其中模型文件在:
~/.kozbox/ppocr-client/paddlex-cache/official_models/
Paddle 自己的缓存放在:
~/.kozbox/ppocr-client/paddle-home/.cache/paddle/
这样不会污染用户目录下其它 Paddle 项目。
坏缓存处理
下载模型时如果中断,可能留下一个“目录存在但文件不完整”的模型目录。
PaddleX 看到目录存在就直接复用,最后报:
No valid PaddlePaddle model found
所以做了一个简单处理:
- 检查模型目录里是否存在
inference.json/inference.pdmodel - 检查是否存在
inference.pdiparams - 如果目录不完整,就重命名为
.corrupt-<timestamp> - 然后重新下载
这样不用手动去删半截模型目录。
最终效果
现在默认配置是:
PP-OCRv6 + gpu:0
启动后自动预热。
实测热启动后的推理耗时大约:
380ms
这个耗时比较符合预期。
第一次启动还是比较慢,因为要初始化和加载权重,但后续会快很多。
备忘
以后如果遇到 GPU 相关问题,先检查:
import paddle
print(paddle.__version__)
print(paddle.is_compiled_with_cuda())
print(paddle.device.cuda.device_count())
如果 is_compiled_with_cuda() 是 False,说明装的是 CPU 版 Paddle。
如果 CUDA 可见但提示 cudnn64_9.dll 找不到,检查:
.venv/Lib/site-packages/nvidia/cudnn/bin
是否存在,并确认该目录已经加入当前进程 PATH / DLL search path。
总结
这个工具(包括套用PaddleOCR框架)本身不复杂。真正花时间的部分是 Windows 下 GPU 推理环境的细节:
- Python ABI
- Paddle GPU wheel 来源
- CUDA runtime
- cuDNN DLL
- PaddleX 缓存
- 首次预热
最终结果还算满意:剪贴板图片进来,本地 CPU/GPU 识别,结果直接复制出去。

浙公网安备 33010602011771号