跳到主要内容

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)

📊 性能对比

模型FUNSDSROIEReCTS平均准确率推理速度
Monkey92.4%97.8%94.5%94.9%⭐⭐⭐⭐
GOT-OCR91.2%98.1%93.2%94.2%⭐⭐⭐
PaddleOCR88.5%95.2%91.8%91.8%⭐⭐⭐⭐⭐
Tesseract75.3%85.4%78.9%79.9%⭐⭐⭐⭐⭐

高分辨率场景

分辨率Monkey其他模型
1080p95.8%94.2%
2K96.2%91.5%
4K96.5%88.3%

💡 最佳实践

  1. 图像预处理

    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)
  2. 分块处理大图

    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: ")
  3. 错误处理

    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
  4. 结果后处理

    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

📚 资源链接

⚠️ 注意事项

  • 首次运行会下载模型(约13GB)
  • 推荐使用A100或RTX 4090(24GB+显存)
  • 处理4K图像需要16GB+显存
  • 量化版本可降低显存需求
  • 注意提示词的设计对结果影响很大

🆚 适用场景

选择 Monkey 当:

  • 处理高分辨率图像(2K+)
  • 文本密集的场景
  • 需要识别小文字
  • 追求高准确率
  • 有充足的GPU资源

选择其他工具当:

  • 追求速度 → PaddleOCR
  • 资源受限 → Tesseract
  • 通用场景 → GOT-OCR
  • 移动端部署 → EasyOCR

🔄 更新日志

  • 2024.06: 优化高分辨率处理
  • 2024.03: 添加量化支持
  • 2023.11: 首次发布