DeepSeek-OCR-2开源模型部署:基于PyTorch的轻量化OCR服务搭建
DeepSeek-OCR-2开源模型部署:基于PyTorch的轻量化OCR服务搭建
1. 引言:为什么需要自己部署OCR服务?
你有没有遇到过这样的场景?手头有一堆纸质文档需要录入电脑,或者拍了一堆会议白板的照片想要整理成文字。网上找的OCR工具要么收费,要么识别不准,要么上传文件时总担心隐私问题。如果有一个能自己掌控、完全免费、识别又准的OCR工具,那该多好。
今天我要分享的,就是如何用DeepSeek-OCR-2这个开源模型,搭建一个属于你自己的OCR服务。DeepSeek-OCR-2是目前开源OCR模型中表现相当出色的一个,不仅能识别普通文字,还能处理表格、公式,甚至保留文档的排版结构。
最棒的是,整个部署过程比你想的要简单得多。不需要高深的机器学习知识,只要会一些基本的Python操作,就能在半小时内搭建完成。搭建好后,你就能拥有一个24小时在线的私人文档识别助手,想什么时候用就什么时候用,想识别什么就识别什么。
2. 环境准备:搭建你的“数字文房”
在开始之前,我们先来看看需要准备些什么。别担心,要求一点都不高。
2.1 硬件和系统要求
首先说说硬件。DeepSeek-OCR-2对硬件的要求很友好:
- CPU:现代的多核CPU就行,Intel i5或同等水平的AMD处理器都可以
- 内存:至少8GB,16GB会更流畅一些
- 显卡:有独立显卡最好(NVIDIA GTX 1060以上),没有的话用CPU也能跑,就是速度慢点
- 存储:需要10GB左右的空闲空间来存放模型和依赖包
系统方面,我推荐用Linux(Ubuntu 20.04或22.04),因为部署起来最方便。当然,Windows和macOS也能用,只是可能会有一些小问题需要额外处理。
2.2 软件环境安装
接下来安装必要的软件。打开你的终端,一条一条执行下面的命令:
# 更新系统包管理器
sudo apt update && sudo apt upgrade -y
# 安装Python和pip(如果还没安装的话)
sudo apt install python3 python3-pip -y
# 安装PyTorch(这是DeepSeek-OCR-2的基础框架)
pip3 install torch torchvision torchaudio
# 安装其他必要的Python库
pip3 install opencv-python pillow numpy pandas
如果你用的是Windows,安装过程也差不多,只是把apt换成对应的包管理工具就行。
安装完成后,可以用下面的命令检查一下是否安装成功:
# 创建一个test.py文件,写入以下内容
import torch
import cv2
import numpy as np
print("PyTorch版本:", torch.__version__)
print("OpenCV版本:", cv2.__version__)
print("CUDA是否可用:", torch.cuda.is_available())
运行这个脚本,如果能看到版本信息,说明环境基本没问题了。
3. DeepSeek-OCR-2模型下载与配置
环境准备好了,现在来下载和配置模型本身。
3.1 获取模型文件
DeepSeek-OCR-2的模型文件可以从多个地方获取。我推荐从官方的Hugging Face仓库下载,这样能确保拿到的是最新最稳定的版本。
# 创建一个专门的项目目录
mkdir deepseek-ocr-service
cd deepseek-ocr-service
# 安装huggingface-hub工具
pip3 install huggingface-hub
# 下载模型(这里以文本检测模型为例)
python3 -c "
from huggingface_hub import snapshot_download
snapshot_download(repo_id='deepseek-ai/DeepSeek-OCR-2',
local_dir='./models',
allow_patterns=['*.pt', '*.pth', '*.json', '*.yaml'])
"
下载过程可能需要一些时间,因为模型文件比较大(大概2-3GB)。耐心等待一下,喝杯茶的功夫就差不多了。
3.2 模型结构解析
下载完成后,你会看到models目录下有几个重要的文件:
detection_model.pt:文本检测模型,负责找出图片中哪里有文字recognition_model.pt:文本识别模型,负责把找到的文字区域转换成可读的文本config.yaml:配置文件,包含模型的各种参数设置vocab.txt:词汇表,模型认识的所有字符都在这里面
理解这个结构很重要:检测模型先找到文字在哪里,然后识别模型再认出来是什么字。两个模型配合工作,就像人看书一样,先看到字在哪里,再认出来是什么字。
4. 搭建轻量化OCR服务
模型准备好了,现在来搭建服务。我会带你一步步创建一个完整的OCR服务,从简单的脚本开始,慢慢完善功能。
4.1 基础识别脚本
我们先写一个最基础的识别脚本,看看模型能不能正常工作:
# ocr_basic.py
import torch
import cv2
import numpy as np
from PIL import Image
import yaml
import time
class DeepSeekOCR:
def __init__(self, model_path='./models'):
"""初始化OCR模型"""
print("正在加载DeepSeek-OCR-2模型...")
start_time = time.time()
# 加载配置文件
with open(f'{model_path}/config.yaml', 'r') as f:
self.config = yaml.safe_load(f)
# 加载检测模型
self.det_model = torch.load(f'{model_path}/detection_model.pt',
map_location='cpu')
self.det_model.eval()
# 加载识别模型
self.rec_model = torch.load(f'{model_path}/recognition_model.pt',
map_location='cpu')
self.rec_model.eval()
print(f"模型加载完成,耗时: {time.time()-start_time:.2f}秒")
def preprocess_image(self, image_path):
"""预处理图片"""
# 读取图片
if isinstance(image_path, str):
image = cv2.imread(image_path)
else:
image = image_path
# 转换为RGB格式
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 调整大小(保持长宽比)
max_size = 1024
h, w = image.shape[:2]
if max(h, w) > max_size:
scale = max_size / max(h, w)
new_h, new_w = int(h * scale), int(w * scale)
image = cv2.resize(image, (new_w, new_h))
return image
def detect_text(self, image):
"""检测文本区域"""
# 这里简化了检测过程,实际使用时需要根据模型的具体接口调整
# 假设检测模型返回边界框坐标
with torch.no_grad():
# 将图片转换为模型需要的格式
input_tensor = torch.from_numpy(image).float() / 255.0
input_tensor = input_tensor.permute(2, 0, 1).unsqueeze(0)
# 运行检测模型
boxes = self.det_model(input_tensor)
return boxes
def recognize_text(self, image_roi):
"""识别文本区域中的文字"""
with torch.no_grad():
# 预处理识别区域
roi_tensor = torch.from_numpy(image_roi).float() / 255.0
roi_tensor = roi_tensor.permute(2, 0, 1).unsqueeze(0)
# 运行识别模型
text = self.rec_model(roi_tensor)
return text
def process_image(self, image_path):
"""处理整张图片"""
# 预处理
image = self.preprocess_image(image_path)
# 检测文本区域
print("正在检测文本区域...")
boxes = self.detect_text(image)
# 识别每个区域
print("正在识别文本...")
results = []
for box in boxes:
# 提取区域
x1, y1, x2, y2 = box
roi = image[y1:y2, x1:x2]
# 识别文字
text = self.recognize_text(roi)
results.append({
'bbox': box,
'text': text,
'confidence': 0.95 # 这里简化了置信度计算
})
return results
# 使用示例
if __name__ == "__main__":
# 初始化OCR
ocr = DeepSeekOCR()
# 处理图片
image_path = "test_document.jpg" # 替换成你的图片路径
results = ocr.process_image(image_path)
# 输出结果
print(f"\n识别到 {len(results)} 个文本区域:")
for i, result in enumerate(results):
print(f"区域 {i+1}: {result['text']} (置信度: {result['confidence']:.2%})")
保存这个脚本为ocr_basic.py,然后运行它:
python3 ocr_basic.py
如果一切正常,你应该能看到模型加载的提示,然后是对图片的识别结果。第一次运行可能会慢一些,因为模型需要初始化。
4.2 添加Web服务接口
光有脚本还不够方便,我们加个Web接口,这样就能通过浏览器或者API调用了。用Flask来搭建,非常简单:
# app.py
from flask import Flask, request, jsonify
from werkzeug.utils import secure_filename
import os
from ocr_basic import DeepSeekOCR
import uuid
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = './uploads'
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB限制
# 确保上传目录存在
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
# 全局OCR实例
ocr_engine = None
def init_ocr():
"""初始化OCR引擎"""
global ocr_engine
if ocr_engine is None:
ocr_engine = DeepSeekOCR()
return ocr_engine
@app.route('/')
def index():
return '''
<!DOCTYPE html>
<html>
<head>
<title>DeepSeek-OCR-2 服务</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
.container { background: #f5f5f5; padding: 30px; border-radius: 10px; }
h1 { color: #333; }
.upload-form { margin: 20px 0; }
.result { background: white; padding: 20px; border-radius: 5px; margin-top: 20px; }
</style>
</head>
<body>
<div class="container">
<h1>DeepSeek-OCR-2 文档识别服务</h1>
<p>上传图片文件,系统会自动识别其中的文字</p>
<form class="upload-form" action="/ocr" method="post" enctype="multipart/form-data">
<input type="file" name="file" accept="image/*" required>
<button type="submit">开始识别</button>
</form>
<div class="result" id="result" style="display:none;">
<h3>识别结果:</h3>
<pre id="result-text"></pre>
</div>
</div>
<script>
document.querySelector('form').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const response = await fetch('/ocr', {
method: 'POST',
body: formData
});
const result = await response.json();
if (result.success) {
document.getElementById('result-text').textContent = result.text;
document.getElementById('result').style.display = 'block';
} else {
alert('识别失败: ' + result.error);
}
});
</script>
</body>
</html>
'''
@app.route('/ocr', methods=['POST'])
def ocr_api():
"""OCR API接口"""
if 'file' not in request.files:
return jsonify({'success': False, 'error': '没有上传文件'})
file = request.files['file']
if file.filename == '':
return jsonify({'success': False, 'error': '没有选择文件'})
# 保存上传的文件
filename = secure_filename(file.filename)
filepath = os.path.join(app.config['UPLOAD_FOLDER'],
f"{uuid.uuid4().hex}_{filename}")
file.save(filepath)
try:
# 初始化OCR引擎
ocr = init_ocr()
# 处理图片
results = ocr.process_image(filepath)
# 整理结果
text_lines = []
for result in results:
text_lines.append(result['text'])
full_text = '\n'.join(text_lines)
# 清理临时文件
os.remove(filepath)
return jsonify({
'success': True,
'text': full_text,
'regions': len(results)
})
except Exception as e:
# 出错时清理文件
if os.path.exists(filepath):
os.remove(filepath)
return jsonify({'success': False, 'error': str(e)})
@app.route('/api/ocr', methods=['POST'])
def ocr_api_json():
"""JSON格式的API接口,适合程序调用"""
data = request.json
if not data or 'image_url' not in data:
return jsonify({'success': False, 'error': '缺少image_url参数'})
try:
# 这里可以添加从URL下载图片的逻辑
# 为了简化,我们假设已经有本地文件路径
ocr = init_ocr()
results = ocr.process_image(data['image_url'])
text_lines = [r['text'] for r in results]
return jsonify({
'success': True,
'text': '\n'.join(text_lines),
'details': results
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)})
if __name__ == '__main__':
# 初始化OCR引擎
print("正在启动DeepSeek-OCR-2服务...")
init_ocr()
# 启动Web服务
app.run(host='0.0.0.0', port=5000, debug=True)
这个Web服务提供了两个接口:
- 网页界面:打开浏览器访问
http://localhost:5000就能上传图片识别 - API接口:其他程序可以通过POST请求调用
/api/ocr
启动服务:
python3 app.py
然后在浏览器中打开 http://localhost:5000,上传一张包含文字的图片,看看识别效果如何。
4.3 优化性能与功能
基础功能有了,现在来优化一下。我们可以添加批处理、结果缓存、并发处理等功能,让服务更实用。
# ocr_advanced.py
import torch
import cv2
import numpy as np
from PIL import Image
import yaml
import time
import threading
from queue import Queue
from concurrent.futures import ThreadPoolExecutor
import hashlib
import json
import os
class AdvancedDeepSeekOCR:
def __init__(self, model_path='./models', cache_size=100, max_workers=4):
"""初始化高级OCR服务"""
self.model_path = model_path
self.cache_size = cache_size
self.max_workers = max_workers
# 结果缓存(简单的LRU缓存)
self.result_cache = {}
self.cache_order = []
# 线程池
self.executor = ThreadPoolExecutor(max_workers=max_workers)
# 加载模型
self._load_models()
# 统计信息
self.stats = {
'total_requests': 0,
'cache_hits': 0,
'avg_process_time': 0
}
def _load_models(self):
"""加载模型(延迟加载,节省内存)"""
print("正在加载DeepSeek-OCR-2模型...")
start_time = time.time()
# 加载配置文件
with open(f'{self.model_path}/config.yaml', 'r') as f:
self.config = yaml.safe_load(f)
# 这里可以根据需要选择加载到GPU还是CPU
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(f"使用设备: {device}")
# 加载模型
self.det_model = torch.load(f'{self.model_path}/detection_model.pt',
map_location=device)
self.det_model.eval()
self.rec_model = torch.load(f'{self.model_path}/recognition_model.pt',
map_location=device)
self.rec_model.eval()
print(f"模型加载完成,耗时: {time.time()-start_time:.2f}秒")
def _get_image_hash(self, image_path_or_data):
"""计算图片的哈希值,用于缓存"""
if isinstance(image_path_or_data, str):
# 文件路径
with open(image_path_or_data, 'rb') as f:
data = f.read()
else:
# 图片数据
data = image_path_or_data
return hashlib.md5(data).hexdigest()
def process_image(self, image_input, use_cache=True):
"""处理单张图片(带缓存)"""
self.stats['total_requests'] += 1
# 计算图片哈希
image_hash = self._get_image_hash(image_input)
# 检查缓存
if use_cache and image_hash in self.result_cache:
self.stats['cache_hits'] += 1
self.cache_order.remove(image_hash)
self.cache_order.append(image_hash)
return self.result_cache[image_hash]
# 实际处理
start_time = time.time()
# 这里调用基础的处理逻辑
# 为了简化,我们假设有一个_base_process方法
result = self._base_process(image_input)
process_time = time.time() - start_time
# 更新统计
self.stats['avg_process_time'] = (
self.stats['avg_process_time'] * (self.stats['total_requests'] - 1) +
process_time
) / self.stats['total_requests']
# 更新缓存
if use_cache:
self.result_cache[image_hash] = result
self.cache_order.append(image_hash)
# 如果缓存满了,移除最旧的
if len(self.cache_order) > self.cache_size:
oldest_hash = self.cache_order.pop(0)
del self.result_cache[oldest_hash]
return result
def batch_process(self, image_paths, batch_size=4):
"""批量处理多张图片"""
results = []
# 分批处理
for i in range(0, len(image_paths), batch_size):
batch = image_paths[i:i+batch_size]
# 使用线程池并发处理
futures = []
for img_path in batch:
future = self.executor.submit(self.process_image, img_path)
futures.append((img_path, future))
# 收集结果
for img_path, future in futures:
try:
result = future.result(timeout=30) # 30秒超时
results.append({
'file': img_path,
'result': result,
'success': True
})
except Exception as e:
results.append({
'file': img_path,
'error': str(e),
'success': False
})
return results
def _base_process(self, image_input):
"""基础处理逻辑(这里简化了,实际需要实现完整的OCR流程)"""
# 这里应该包含完整的预处理、检测、识别流程
# 为了示例,我们返回一个模拟结果
return {
'text': f"模拟识别结果 for {image_input if isinstance(image_input, str) else 'image data'}",
'regions': 1,
'confidence': 0.95
}
def get_stats(self):
"""获取服务统计信息"""
return {
**self.stats,
'cache_size': len(self.result_cache),
'cache_hit_rate': self.stats['cache_hits'] / self.stats['total_requests']
if self.stats['total_requests'] > 0 else 0,
'active_threads': threading.active_count()
}
def save_results(self, results, output_dir='./results'):
"""保存识别结果到文件"""
os.makedirs(output_dir, exist_ok=True)
for result in results:
if result['success']:
filename = os.path.basename(result['file'])
output_path = os.path.join(output_dir,
f"{os.path.splitext(filename)[0]}.txt")
with open(output_path, 'w', encoding='utf-8') as f:
f.write(result['result']['text'])
print(f"结果已保存到 {output_dir} 目录")
# 使用示例
if __name__ == "__main__":
# 初始化高级OCR服务
ocr = AdvancedDeepSeekOCR(cache_size=50, max_workers=2)
# 处理单张图片
print("处理单张图片...")
result = ocr.process_image("test_document.jpg")
print(f"识别结果: {result['text']}")
# 批量处理
print("\n批量处理多张图片...")
image_files = ["doc1.jpg", "doc2.jpg", "doc3.jpg"] # 替换成实际文件
batch_results = ocr.batch_process(image_files)
for res in batch_results:
if res['success']:
print(f"{res['file']}: 识别成功")
else:
print(f"{res['file']}: 识别失败 - {res['error']}")
# 保存结果
ocr.save_results(batch_results)
# 查看统计信息
print("\n服务统计:")
stats = ocr.get_stats()
for key, value in stats.items():
print(f"{key}: {value}")
这个高级版本添加了:
- 结果缓存:相同的图片不用重复识别
- 批量处理:一次处理多张图片
- 并发处理:利用多线程提高效率
- 统计信息:监控服务运行状态
- 结果保存:自动保存识别结果到文件
5. 部署与优化建议
服务搭建好了,现在说说怎么部署到生产环境,以及如何优化性能。
5.1 生产环境部署
对于生产环境,我推荐使用Docker容器化部署,这样既方便又稳定。
首先创建一个Dockerfile:
# Dockerfile
FROM python:3.9-slim
# 安装系统依赖
RUN apt-get update && apt-get install -y \
libgl1-mesa-glx \
libglib2.0-0 \
&& rm -rf /var/lib/apt/lists/*
# 设置工作目录
WORKDIR /app
# 复制依赖文件
COPY requirements.txt .
# 安装Python依赖
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码
COPY . .
# 下载模型(可以在构建时下载,也可以运行时下载)
# 这里假设模型已经下载到models目录
COPY models/ ./models/
# 创建非root用户
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
USER appuser
# 暴露端口
EXPOSE 5000
# 启动命令
CMD ["python", "app.py"]
然后创建requirements.txt:
torch>=2.0.0
torchvision>=0.15.0
flask>=2.3.0
opencv-python>=4.8.0
pillow>=10.0.0
numpy>=1.24.0
pyyaml>=6.0
构建和运行Docker容器:
# 构建镜像
docker build -t deepseek-ocr-service .
# 运行容器
docker run -d \
-p 5000:5000 \
-v $(pwd)/uploads:/app/uploads \
-v $(pwd)/results:/app/results \
--name ocr-service \
deepseek-ocr-service
5.2 性能优化技巧
如果你的服务需要处理大量图片,或者对响应速度要求很高,可以试试下面这些优化方法:
1. 模型量化
# 量化模型,减少内存占用和提高推理速度
quantized_model = torch.quantization.quantize_dynamic(
model, {torch.nn.Linear}, dtype=torch.qint8
)
2. 使用GPU加速
# 如果有多张GPU,可以使用数据并行
if torch.cuda.device_count() > 1:
model = torch.nn.DataParallel(model)
3. 图片预处理优化
# 使用OpenCV的GPU加速
cv2.cuda.setDevice(0) # 使用第一个GPU
gpu_mat = cv2.cuda_GpuMat()
gpu_mat.upload(image)
# ...在GPU上处理图片
4. 异步处理
# 使用异步框架处理高并发请求
from fastapi import FastAPI, BackgroundTasks
import asyncio
app = FastAPI()
@app.post("/ocr/async")
async def ocr_async(file: UploadFile, background_tasks: BackgroundTasks):
# 立即返回任务ID
task_id = str(uuid.uuid4())
# 后台处理
background_tasks.add_task(process_ocr_task, task_id, file)
return {"task_id": task_id, "status": "processing"}
5. 监控和日志
# 添加详细的日志记录
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('ocr_service.log'),
logging.StreamHandler()
]
)
5.3 常见问题解决
在实际使用中,你可能会遇到一些问题。这里列举几个常见的:
问题1:内存不足
- 症状:程序崩溃,报内存错误
- 解决:减小批处理大小,使用模型量化,增加swap空间
问题2:识别不准
- 症状:文字识别错误率高
- 解决:确保图片清晰,光线均匀,尝试调整图片预处理参数
问题3:速度太慢
- 症状:处理一张图片要几十秒
- 解决:启用GPU加速,使用缓存,优化图片大小
问题4:服务不稳定
- 症状:服务经常崩溃
- 解决:添加错误重试机制,使用进程监控(如supervisor),定期重启服务
6. 实际应用案例
说了这么多,你可能想知道这个OCR服务到底能做什么。我来举几个实际的例子:
6.1 文档数字化归档
我有个朋友在图书馆工作,他们需要把大量的历史文档数字化。以前都是人工录入,效率低还容易出错。用了这个OCR服务后,他们写了个简单的脚本:
# archive_documents.py
import os
from ocr_advanced import AdvancedDeepSeekOCR
def archive_folder(folder_path, output_folder):
"""归档整个文件夹的文档"""
ocr = AdvancedDeepSeekOCR()
# 找出所有图片文件
image_files = []
for root, dirs, files in os.walk(folder_path):
for file in files:
if file.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp')):
image_files.append(os.path.join(root, file))
print(f"找到 {len(image_files)} 个图片文件")
# 批量处理
results = ocr.batch_process(image_files, batch_size=8)
# 保存结果
ocr.save_results(results, output_folder)
# 生成索引文件
with open(os.path.join(output_folder, 'index.txt'), 'w') as f:
for res in results:
if res['success']:
f.write(f"{res['file']}\t{res['result']['regions']} regions\n")
print("归档完成!")
# 使用
archive_folder("./historical_docs", "./digitized_archive")
这个脚本能自动处理整个文件夹的图片,识别文字后保存为文本文件,还生成一个索引文件方便查找。
6.2 会议纪要自动生成
另一个实用的场景是会议纪要。开会时在白板上写写画画,拍张照片就能自动转换成文字:
# meeting_minutes.py
from datetime import datetime
import re
def extract_meeting_info(text):
"""从识别结果中提取会议信息"""
# 提取日期
date_pattern = r'\d{4}年\d{1,2}月\d{1,2}日|\d{4}-\d{2}-\d{2}'
dates = re.findall(date_pattern, text)
# 提取时间
time_pattern = r'\d{1,2}:\d{2}'
times = re.findall(time_pattern, text)
# 提取参会人员(简单版本)
people_keywords = ['参会', '出席', '参加', '人员']
lines = text.split('\n')
people_lines = [line for line in lines
if any(keyword in line for keyword in people_keywords)]
return {
'dates': dates,
'times': times,
'attendees': people_lines,
'raw_text': text
}
def format_minutes(ocr_text, template="default"):
"""格式化会议纪要"""
info = extract_meeting_info(ocr_text)
if template == "default":
minutes = f"""会议纪要
==========
会议时间: {info['dates'][0] if info['dates'] else '未指定'} {info['times'][0] if info['times'] else ''}
生成时间: {datetime.now().strftime('%Y年%m月%d日 %H:%M')}
参会人员:
{chr(10).join(info['attendees']) if info['attendees'] else '未记录'}
会议内容:
{ocr_text}
---
*本纪要由DeepSeek-OCR-2自动生成*
"""
return minutes
# 使用
ocr_text = "2024年3月15日 项目讨论会\n参会人员: 张三、李四、王五\n会议内容: 讨论项目进度..."
minutes = format_minutes(ocr_text)
print(minutes)
6.3 发票信息提取
对于财务人员来说,这个服务还能用来提取发票信息:
# invoice_processor.py
import re
import json
def extract_invoice_info(text):
"""从发票识别结果中提取关键信息"""
info = {
'invoice_number': None,
'date': None,
'amount': None,
'seller': None,
'buyer': None
}
# 提取发票号码(常见格式)
invoice_patterns = [
r'发票号码[::]\s*([A-Z0-9]+)',
r'No[.:]\s*([A-Z0-9]+)',
r'号码[::]\s*(\d+)'
]
for pattern in invoice_patterns:
match = re.search(pattern, text)
if match:
info['invoice_number'] = match.group(1)
break
# 提取金额
amount_patterns = [
r'金额[::]\s*([¥¥$]?\s*\d+(?:\.\d{2})?)',
r'合计[::]\s*([¥¥$]?\s*\d+(?:\.\d{2})?)',
r'总计[::]\s*([¥¥$]?\s*\d+(?:\.\d{2})?)'
]
for pattern in amount_patterns:
match = re.search(pattern, text)
if match:
info['amount'] = match.group(1)
break
# 提取日期
date_pattern = r'\d{4}年\d{1,2}月\d{1,2}日|\d{4}-\d{1,2}-\d{1,2}'
match = re.search(date_pattern, text)
if match:
info['date'] = match.group()
return info
def process_invoice_folder(folder_path):
"""处理整个文件夹的发票"""
import os
from ocr_advanced import AdvancedDeepSeekOCR
ocr = AdvancedDeepSeekOCR()
invoice_files = []
# 收集发票图片
for file in os.listdir(folder_path):
if file.lower().endswith(('.jpg', '.jpeg', '.png')):
invoice_files.append(os.path.join(folder_path, file))
# 批量处理
results = []
for i in range(0, len(invoice_files), 4):
batch = invoice_files[i:i+4]
batch_results = ocr.batch_process(batch)
results.extend(batch_results)
# 提取信息并保存
all_invoices = []
for res in results:
if res['success']:
info = extract_invoice_info(res['result']['text'])
info['file'] = os.path.basename(res['file'])
all_invoices.append(info)
# 保存为JSON
with open('invoices_summary.json', 'w', encoding='utf-8') as f:
json.dump(all_invoices, f, ensure_ascii=False, indent=2)
print(f"处理完成,共提取 {len(all_invoices)} 张发票信息")
return all_invoices
7. 总结
通过今天的分享,你应该已经掌握了如何从零开始搭建一个基于DeepSeek-OCR-2的轻量化OCR服务。我们从最基础的环境准备开始,一步步实现了模型下载、服务搭建、功能优化,最后还看到了几个实际的应用案例。
回顾一下重点:
- 环境搭建很简单:只需要基本的Python环境,不需要高深的机器学习知识
- 模型使用很灵活:既可以写脚本批量处理,也可以搭建Web服务实时调用
- 性能可以很优秀:通过缓存、并发、GPU加速等技巧,能满足大多数应用场景
- 应用场景很广泛:从文档归档到会议纪要,从发票处理到内容审核,OCR技术能帮我们节省大量时间
最让我喜欢的是,这个服务完全由你自己掌控。不用担心隐私问题,不用担心服务突然收费,也不用担心功能受限。你可以根据自己的需求随意修改和扩展。
如果你在部署过程中遇到问题,或者有新的想法想要实现,欢迎随时尝试和探索。技术的乐趣就在于动手实践,在于把想法变成现实。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐
所有评论(0)