Monkey OCR
Monkey 是一个专为文本密集场景设计的OCR模型,特别擅长处理高分辨率图像中的小文字、密集文本和复杂版面,在文档理解和场景文字识别方面表现优异。
🌟 核心特性
- ✅ 高分辨率支持:原生支持高达4K分辨率的图像
- ✅ 文本密集处理:擅长识别密集排列的小文字
- ✅ 端到端架构:统一的视觉-语言模型
- ✅ 多任务支持:OCR、VQA、文档理解等
- ✅ 窗口注意力:高效处理长图像
- ✅ 中英文优化:特别优化中英文混合场景
- ✅ 实时推理:优化的推理速度
📦 安装与使用
环境准备
# 创建环境
conda create -n monkey python=3.10
conda activate monkey
# 安装依赖
pip install torch torchvision
pip install transformers
pip install accelerate bitsandbytes
# 安装 Monkey
git clone https://github.com/Yuliang-Liu/Monkey.git
cd Monkey
pip install -e .
快速开始
from monkey import MonkeyModel
from PIL import Image
# 加载模型
model = MonkeyModel.from_pretrained(
"echo840/Monkey",
trust_remote_code=True
)
# 加载图像
image = Image.open("document.jpg")
# OCR识别
result = model.generate(
image,
prompt="请识别图像中的所有文字"
)
print(result)
不同任务模式
# 1. 纯OCR任务
text = model.generate(
image,
prompt="OCR: "
)
# 2. 文档理解
understanding = model.generate(
image,
prompt="描述这份文档的主要内容和结构"
)
# 3. 视觉问答
answer = model.generate(
image,
prompt="图中提到的销售额是多少?"
)
# 4. 表格提取
table = model.generate(
image,
prompt="提取图中的表格,以Markdown格式输出"
)
🏗️ 技术架构
graph TB
A[高分辨率图像] --> B[图像分块]
B --> C[窗口注意力编码器]
C --> D[多尺度特征融合]
E[文本提示] --> F[语言模型]
D --> F
F --> G[自回归生成]
G --> H[输出结果]
B -->|Patch Partition| B1[图像块序列]
C -->|Shifted Window| C1[局部特征]
D -->|Cross-Attention| D1[全局特征]
G -->|LLaMA| G1[文本生成]
关键技术
1. 窗口注意力机制
# 处理高分辨率图像的关键
class WindowAttention:
"""窗口注意力,降低计算复杂度"""
def __init__(self, window_size=7):
self.window_size = window_size
def forward(self, x):
# 将图像分成窗口
# 在每个窗口内计算注意力
# 复杂度从O(n²)降到O(n*w²)
pass
2. 多尺度特征融合
# 融合不同尺度的特征
class MultiScaleFusion:
"""多尺度特征融合"""
def __init__(self):
self.scales = [1, 2, 4, 8]
def forward(self, features):
# 提取多个尺度的特征
# 融合得到丰富的表示
pass
🎯 应用场景
1. 文本密集场景OCR
from monkey import MonkeyModel
from PIL import Image
def dense_text_ocr(image_path):
"""处理文本密集图像"""
model = MonkeyModel.from_pretrained("echo840/Monkey")
image = Image.open(image_path)
# 高分辨率模式
result = model.generate(
image,
prompt="识别所有文字,保持原有排版",
max_resolution=True, # 使用最高分辨率
preserve_layout=True
)
return result
# 适用于:报纸、杂志、密集排版的文档
text = dense_text_ocr("newspaper.jpg")
2. 学术论文识别
def recognize_academic_paper(image_path):
"""识别学术论文"""
model = MonkeyModel.from_pretrained("echo840/Monkey")
image = Image.open(image_path)
# 学术论文通常包含:标题、作者、摘要、正文、公式、参考文献
result = model.generate(
image,
prompt="""
请识别这篇学术论文的内容,包括:
1. 标题
2. 作者信息
3. 摘要
4. 正文(保持章节结构)
5. 数学公式(LaTeX格式)
6. 参考文献
以结构化格式输出。
"""
)
return result
3. 票据识别
def extract_receipt_info(image_path):
"""提取票据信息"""
model = MonkeyModel.from_pretrained("echo840/Monkey")
image = Image.open(image_path)
result = model.generate(
image,
prompt="""
请提取票据中的关键信息:
- 商家名称
- 日期时间
- 商品清单(名称、数量、单价、小计)
- 总金额
- 支付方式
以JSON格式输出。
"""
)
# 解析JSON
import json
info = json.loads(result)
return info
4. 屏幕截图OCR
def screenshot_ocr(image_path):
"""识别屏幕截图中的文字"""
model = MonkeyModel.from_pretrained("echo840/Monkey")
image = Image.open(image_path)
# 屏幕截图通常是高分辨率
result = model.generate(
image,
prompt="提取截图中的所有文字内容",
high_quality=True
)
return result
# 适用于:UI截图、代码截图、聊天记录截图等
text = screenshot_ocr("screenshot.png")
5. 多页文档批处理
from pathlib import Path
import json
def batch_ocr_documents(input_dir, output_dir):
"""批量处理文档"""
model = MonkeyModel.from_pretrained("echo840/Monkey")
input_path = Path(input_dir)
output_path = Path(output_dir)
output_path.mkdir(exist_ok=True)
results = []
for img_file in input_path.glob("*.png"):
try:
print(f"处理: {img_file.name}")
image = Image.open(img_file)
text = model.generate(
image,
prompt="OCR识别所有文字"
)
# 保存文本
txt_file = output_path / f"{img_file.stem}.txt"
with open(txt_file, "w", encoding="utf-8") as f:
f.write(text)
results.append({
"file": img_file.name,
"status": "success",
"chars": len(text)
})
except Exception as e:
results.append({
"file": img_file.name,
"status": "error",
"error": str(e)
})
# 保存报告
with open(output_path / "report.json", "w") as f:
json.dump(results, f, indent=2, ensure_ascii=False)
return results
6. 文档问答
def document_qa(image_path, questions):
"""基于文档的问答"""
model = MonkeyModel.from_pretrained("echo840/Monkey")
image = Image.open(image_path)
answers = {}
for question in questions:
answer = model.generate(
image,
prompt=f"问题:{question}\n请基于图像内容回答:"
)
answers[question] = answer
return answers
# 示例
questions = [
"这份文档的标题是什么?",
"文中提到的关键数据有哪些?",
"作者的联系方式是什么?"
]
answers = document_qa("document.jpg", questions)
for q, a in answers.items():
print(f"Q: {q}")
print(f"A: {a}\n")
🔧 高级配置
性能优化
from monkey import MonkeyModel
import torch
# 使用量化加速
model = MonkeyModel.from_pretrained(
"echo840/Monkey",
load_in_8bit=True, # 8-bit量化
device_map="auto", # 自动设备分配
torch_dtype=torch.float16 # 半精度
)
# 批量推理
images = [Image.open(f"page_{i}.jpg") for i in range(10)]
results = model.batch_generate(
images,
prompt="OCR: ",
batch_size=4
)
自定义分辨率
# 处理超高分辨率图像
result = model.generate(
image,
prompt="OCR: ",
max_pixels=4096*4096, # 最大像素数
resize_mode="adaptive", # 自适应调整
maintain_aspect_ratio=True # 保持宽高比
)
提示词工程
# 精细控制输出格式
result = model.generate(
image,
prompt="""
你是一个专业的OCR助手。请按以下要求识别图像:
要求:
1. 准确识别所有文字,包括标点符号
2. 保持原始排版和段落结构
3. 数字和字母不要混淆
4. 对于表格,使用Markdown表格格式
5. 对于公式,使用LaTeX格式
6. 标注不确定的字符为[?]
输出格式:纯文本,保持原始格式
""",
temperature=0.1, # 降低随机性
top_p=0.9,
max_length=4096
)
流式输出
# 实时查看生成过程
for chunk in model.generate_stream(
image,
prompt="详细描述图像内容:"
):
print(chunk, end="", flush=True)
📊 性能对比
| 模型 | FUNSD | SROIE | ReCTS | 平均准确率 | 推理速度 |
|---|---|---|---|---|---|
| Monkey | 92.4% | 97.8% | 94.5% | 94.9% | ⭐⭐⭐⭐ |
| GOT-OCR | 91.2% | 98.1% | 93.2% | 94.2% | ⭐⭐⭐ |
| PaddleOCR | 88.5% | 95.2% | 91.8% | 91.8% | ⭐⭐⭐⭐⭐ |
| Tesseract | 75.3% | 85.4% | 78.9% | 79.9% | ⭐⭐⭐⭐⭐ |
高分辨率场景
| 分辨率 | Monkey | 其他模型 |
|---|---|---|
| 1080p | 95.8% | 94.2% |
| 2K | 96.2% | 91.5% |
| 4K | 96.5% | 88.3% |
💡 最佳实践
-
图像预处理
from PIL import Image, ImageEnhance
# 提升对比度
image = Image.open("document.jpg")
enhancer = ImageEnhance.Contrast(image)
image = enhancer.enhance(1.3)
# 锐化
from PIL import ImageFilter
image = image.filter(ImageFilter.SHARPEN) -
分块处理大图
def process_large_image(image_path):
"""分块处理大图像"""
image = Image.open(image_path)
# 如果图像过大,分块处理
if image.width * image.height > 4096*4096:
# 切分图像
chunks = split_image(image, chunk_size=2048)
# 分别处理
results = []
for chunk in chunks:
result = model.generate(chunk, prompt="OCR: ")
results.append(result)
# 合并结果
return "\n".join(results)
else:
return model.generate(image, prompt="OCR: ") -
错误处理
def robust_ocr(image_path, max_retries=3):
"""带重试的OCR"""
for i in range(max_retries):
try:
image = Image.open(image_path)
result = model.generate(image, prompt="OCR: ")
return result
except Exception as e:
print(f"尝试 {i+1} 失败: {e}")
if i == max_retries - 1:
return None -
结果后处理
def post_process_ocr(text):
"""后处理OCR结果"""
# 修正常见错误
corrections = {
"O": "0", # 字母O -> 数字0(在数字上下文中)
"l": "1", # 字母l -> 数字1(在数字上下文中)
"S": "5", # 在特定上下文
}
# 移除多余空格
text = " ".join(text.split())
# 修正标点
text = text.replace(" ,", ",")
text = text.replace(" .", ".")
return text
📚 资源链接
- GitHub: https://github.com/Yuliang-Liu/Monkey
- 论文: https://arxiv.org/abs/2311.06607
- 模型: https://huggingface.co/echo840/Monkey
- Demo: https://huggingface.co/spaces/echo840/Monkey
⚠️ 注意事项
- 首次运行会下载模型(约13GB)
- 推荐使用A100或RTX 4090(24GB+显存)
- 处理4K图像需要16GB+显存
- 量化版本可降低显存需求
- 注意提示词的设计对结果影响很大
🆚 适用场景
选择 Monkey 当:
- 处理高分辨率图像(2K+)
- 文本密集的场景
- 需要识别小文字
- 追求高准确率
- 有充足的GPU资源
选择其他工具当:
- 追求速度 → PaddleOCR
- 资源受限 → Tesseract
- 通用场景 → GOT-OCR
- 移动端部署 → EasyOCR
🔄 更新日志
- 2024.06: 优化高分辨率处理
- 2024.03: 添加量化支持
- 2023.11: 首次发布