我在尝试把我的图片转换为文字,恰好看到百度开源了Unlimited-ocr项目,就想把它部署到自己的Windows电脑上,并提供给其他大模型使用。
Unlimited-ocr: https://github.com/baidu/Unlimited-OCR
我开源的代码: https://github.com/tinygone/unlimited-ocr-mcp-server
问题
先让Claude Code分析了这个github repo,给了很多输出,意思是可以帮我安装。我本能拒绝,因为我自己都没看清楚它会怎么使用,更不知道它到底给我安装了啥。
我担心的几个问题:
1、都给我安装到C盘了
2、模型不知道下载到哪
3、官方的仓库里面几乎没有代码,readme里面有一点,我也不知道怎么调用它。
准备
本机是Windows11操作系统,Nvidia RTX5070TI显卡,CUDA版本是13.1,安装了Anaconda,所以会使用conda管理python环境。
unlimited-ocr官网显示推荐使用python 3.12.3 + CUDA12.9,但是在pytorch官网安装已经找不到CUDA12.9,所以我还是决定把我的CUDA升级一下,然后安装最新的CUDA。
升级前:

安装后

安装过程
1 创建项目目录 D:/aiworkspace/uocr-workspace(可选),并创建虚拟环境uocr
conda create -n uocr python=3.12.3
conda activate uocr
2 安装pytorch,访问官网 https://pytorch.org/get-started ,获取最新的安装链接
pip3 install torch torchvision --index-url https://download.pytorch.org/whl/cu132
3 安装其他依赖,在uocr-workspace下创建一个requirements.txt文件,内容来自repo里面的readme.md,我把torch和torchvision删除:
transformers==4.57.1
Pillow==12.1.1
matplotlib==3.10.8
einops==0.8.2
addict==2.4.0
easydict==1.13
pymupdf==1.27.2.2
psutil==7.2.2
执行如下命令安装依赖:
pip install -r requirements.txt
4 初步验证,执行下面的命令
python -c "import torch; print('torch:', torch.__version__); print('cuda:', torch.cuda.is_available()); print('device:', torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'CPU only')"
输出如下,说明正常:
torch: 2.13.0+cu132
cuda: True
device: NVIDIA GeForce RTX 5070 Ti Laptop GPU
5 设置环境变量:通过代理访问HuggingFace;设置模型下载的目录,不然就会下载到C盘。
powershell
$env:HF_ENDPOINT = "https://hf-mirror.com"
echo $env:HF_ENDPOINT
$env:HF_HOME = "E:\hgcache"
echo $env:HF_HOME
6 创建run_ocr.py,内容如下:
"""
Unlimited-OCR 推理脚本
用法:
# 单张图片(gundam 配置,适合大图)
python run_ocr.py --mode single -i inputs/test.jpg -o outputs
# 多张图片
python run_ocr.py --mode multi -i inputs/page1.png inputs/page2.png -o outputs
# PDF(自动转图后走多页)
python run_ocr.py --mode pdf -i inputs/doc.pdf -o outputs --dpi 300
"""
import argparse
import os
import time
import torch
from transformers import AutoModel, AutoTokenizer
MODEL_NAME = 'baidu/Unlimited-OCR'
def load_model():
print('[1/3] 加载 tokenizer 和模型 ...')
t0 = time.time()
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True)
model = AutoModel.from_pretrained(
MODEL_NAME,
trust_remote_code=True,
use_safetensors=True,
torch_dtype=torch.bfloat16,
)
model = model.eval().cuda()
print(f' 模型加载完成,耗时 {time.time() - t0:.1f}s')
if torch.cuda.is_available():
print(f' GPU: {torch.cuda.get_device_name(0)}')
return tokenizer, model
def infer_single(tokenizer, model, image_file, output_dir):
print(f'[2/3] 单图推理: {image_file}')
model.infer(
tokenizer,
prompt='<image>document parsing.',
image_file=image_file,
output_path=output_dir,
base_size=1024, image_size=640, crop_mode=True, # gundam 配置
max_length=32768,
no_repeat_ngram_size=35, ngram_window=128,
save_results=True,
)
def infer_multi(tokenizer, model, image_files, output_dir):
print(f'[2/3] 多页推理: {len(image_files)} 张图')
model.infer_multi(
tokenizer,
prompt='<image>Multi page parsing.',
image_files=image_files,
output_path=output_dir,
image_size=1024,
max_length=32768,
no_repeat_ngram_size=35, ngram_window=1024,
save_results=True,
)
def pdf_to_images(pdf_path, dpi=300):
import tempfile
import fitz # PyMuPDF
print(f' PDF 转图: {pdf_path} (dpi={dpi})')
doc = fitz.open(pdf_path)
tmp_dir = tempfile.mkdtemp(prefix='pdf_ocr_')
mat = fitz.Matrix(dpi / 72, dpi / 72)
paths = []
for i, page in enumerate(doc):
out = os.path.join(tmp_dir, f'page_{i+1:04d}.png')
page.get_pixmap(matrix=mat).save(out)
paths.append(out)
doc.close()
print(f' 转出 {len(paths)} 页 -> {tmp_dir}')
return paths
def main():
parser = argparse.ArgumentParser(description='Unlimited-OCR runner')
parser.add_argument('--mode', choices=['single', 'multi', 'pdf'], default='single',
help='推理模式: single=单图, multi=多图, pdf=PDF')
parser.add_argument('-i', '--inputs', nargs='+', required=True,
help='输入文件路径(single/multi 传图片, pdf 传 .pdf)')
parser.add_argument('-o', '--output', default='outputs', help='输出目录')
parser.add_argument('--dpi', type=int, default=300, help='PDF 转图 DPI (仅 pdf 模式)')
args = parser.parse_args()
os.makedirs(args.output, exist_ok=True)
tokenizer, model = load_model()
if args.mode == 'single':
infer_single(tokenizer, model, args.inputs[0], args.output)
elif args.mode == 'multi':
infer_multi(tokenizer, model, args.inputs, args.output)
elif args.mode == 'pdf':
images = pdf_to_images(args.inputs[0], args.dpi)
infer_multi(tokenizer, model, images, args.output)
print(f'[3/3] 完成. 结果目录: {os.path.abspath(args.output)}')
if __name__ == '__main__':
t = time.time()
main()
print(f'总耗时: {time.time() - t:.1f}s')
7 单次调用测试如下命令,首先会下载模型,程序会先下载模型,然后执行识别任务。
python run_ocr.py --mode single -i inputs/1.jpg -o outputs
8 为了能让大模型调用unlimited-ocr,需要运行serve_ocr.py,启动一个http服务,既兼容OpenAI 兼容 API 服务,可以为dify/claude code提供模型服务,也可以作为一个独立的http服务。
python serve_ocr.py
9 创建mcp,核心文件是ocr_mcp_server.py,然后可以让claude code把这个mcp加入进去。
10 引入skill,见.claude/skills/uocr
11 在Claude Code中执行效果:
/uocr 识别 inputs/2.png,告诉我内容
