参考 MinerU 实现的模型统一框架,针对金融场景设计。
| 场景类型 | 特点 | 表格形式 |
|---|---|---|
| 银行交易流水 | 单栏列表形式,无合并单元格 | 有线表格 / 无线表格 |
| 财务报表 | 多栏列表形式,有合并单元格,表头复杂 | 有线表格 / 无线表格 |
| 模型类型 | 推荐模型 | 说明 |
|---|---|---|
| 版式检测 | Docling Layout / DocLayout-YOLO | HuggingFace 或 MinerU 模型 |
| 文字识别 | PaddleOCR (PyTorch) | 效果好,支持角度校正 |
| 表格结构识别 | MinerU VLM / PaddleOCR-VL | VLM 返回 HTML 结构 |
| 公式识别 | MinerU VLM | 返回 LaTeX |
| 方向识别 | PP-LCNet | 沿用 MinerU 实现 |
| 单元格坐标匹配 | TableCellMatcher | OCR 检测框与 VLM 结构匹配 |
graph TB
A[输入 PDF/图片] --> B{PDF 分类}
B -->|扫描件/图片| C1[页面方向识别<br/>PP-LCNet]
B -->|数字原生PDF| D
C1 --> D[Layout 检测<br/>去重叠框]
D --> E[整页 OCR<br/>获取所有 text spans]
E --> F[Span-Block 匹配<br/>SpanMatcher]
F --> G{元素分类}
G --> H[文本类]
G --> I[表格类]
G --> J[图片类]
G --> K[公式类]
G --> L[丢弃类]
subgraph 文本处理
H --> H1{有匹配的spans?}
H1 -->|是| H2[合并 spans 文本]
H1 -->|否| H3{PDF类型?}
H3 -->|数字PDF| H4[PDF 字符提取]
H4 --> H5{成功?}
H5 -->|否| H6[裁剪区域 OCR]
H5 -->|是| H7[文本结果]
H3 -->|扫描件| H6
H6 --> H7
H2 --> H7
end
subgraph 表格处理
I --> I1[OCR 检测<br/>获取文本框坐标]
I --> I2[VLM 结构识别<br/>返回 HTML]
I1 --> I3[坐标匹配<br/>TableCellMatcher]
I2 --> I3
I3 --> I4[带坐标的表格]
end
subgraph 图片处理
J --> J1[裁剪保存]
end
subgraph 公式处理
K --> K1[VLM 识别<br/>返回 LaTeX]
end
subgraph 丢弃元素
L --> L1{有匹配的spans?}
L1 -->|是| L2[合并 spans 文本]
L1 -->|否| L3[裁剪区域 OCR]
L2 --> L4[保留备用]
L3 --> L4
end
H7 --> M[合并所有结果]
I4 --> M
J1 --> M
K1 --> M
L4 --> M
M --> N[按阅读顺序排序]
N --> O[坐标转换回原图]
O --> P[合并跨页表格]
P --> Q[金额数字标准化]
Q --> R[多格式输出]
参考 MinerU 的处理方式,新流程采用 整页 OCR → Span-Block 匹配 策略:
优势:
| 元素类别 | 包含类型 | 处理方式 |
|---|---|---|
| 文本类 | text, title, header, footer, ref_text, table_caption, image_caption 等 | 优先使用匹配的 spans,否则 PDF 提取或裁剪 OCR |
| 表格类 | table, table_body | OCR 坐标 + VLM 结构 |
| 图片类 | image, image_body, figure | 裁剪保存 |
| 公式类 | interline_equation, equation | VLM 识别 |
| 丢弃类 | abandon, discarded | 优先使用匹配的 spans,否则裁剪 OCR |
| 处理阶段 | 方向识别 | 建议 |
|---|---|---|
| 页面级 | PP-LCNet | 可配置,扫描件开启,数字PDF关闭 |
| 表格区域 | - | 可选,VLM 有一定容忍度,OCR 自带角度校正 |
| 文本区域 | - | 不需要,OCR 自带校正 |
当Layout检测将大面积的表格区域误识别为文本框时,可以通过后处理自动转换:
判断规则:
配置示例:
layout:
convert_large_text_to_table: true # 是否启用
min_text_area_ratio: 0.25 # 最小面积占比(25%)
min_text_width_ratio: 0.4 # 最小宽度占比(40%)
min_text_height_ratio: 0.3 # 最小高度占比(30%)
详细说明请参考:Layout后处理-文本转表格.md
| PDF 类型 | 文字块处理 | 表格处理 |
|---|---|---|
| 扫描件/图片 | 整页 OCR → Span 匹配 | OCR 检测(坐标) + VLM(结构) |
| 数字原生 PDF | 整页 OCR → Span 匹配 / PDF 字符提取 | OCR 检测(坐标) + VLM(结构) |
关键点:
默认参数(已优化,参考PPStructureV3):
det_threshold: 0.6(检测框置信度阈值,提高可减少噪声框)unclip_ratio: 1.5(检测框扩展比例,降低可提高框精确度)enable_merge_det_boxes: False(是否合并检测框,表格场景建议False)配置示例:
ocr:
det_threshold: 0.6 # 检测阈值(0.3-0.7,越高越严格)
unclip_ratio: 1.5 # 扩展比例(1.3-1.8,越低越精确)
enable_merge_det_boxes: false # 合并框(表格场景建议false)
language: ch # 语言(ch/ch_lite/en等)
参数调优建议:
det_threshold=0.6, enable_merge_det_boxes=falsedet_threshold=0.4, enable_merge_det_boxes=truedet_threshold=0.3, unclip_ratio=1.8详细分析请参考:OCR识别差异分析与改进方案.md
universal_doc_parser/
├── config/ # 配置文件
│ ├── bank_statement_yusys_v2.yaml # 银行流水配置(Docling + PaddleOCR-VL)
│ ├── bank_statement_mineru_v2.yaml # 银行流水配置(MinerU layout + MinerU VLM)
│ ├── bank_statement_mineru_vl.yaml # 银行流水配置(MinerU VLM)
│ └── bank_statement_paddle_vl.yaml # 银行流水配置(PaddleOCR-VL)
│
├── core/ # 核心处理模块
│ ├── pipeline_manager_v2.py # 主流水线管理器 ⭐
│ ├── element_processors.py # 元素处理器(文本、表格、图片等)
│ ├── coordinate_utils.py # 坐标转换工具
│ ├── layout_utils.py # 布局处理工具(排序、去重、SpanMatcher)⭐
│ ├── pdf_utils.py # PDF 处理工具
│ ├── config_manager.py # 配置管理
│ └── model_factory.py # 模型工厂
│
├── models/ # 模型适配器
│ └── adapters/
│ ├── base.py # 适配器基类
│ ├── mineru_adapter.py # MinerU 适配器
│ ├── paddle_vl_adapter.py # PaddleOCR-VL 适配器
│ ├── paddle_layout_detector.py # PaddleX RT-DETR 布局检测器
│ └── docling_layout_adapter.py # Docling 布局检测器 ⭐
│
├── utils/ # 输出工具模块
│ ├── output_formatter_v2.py # 统一输出格式化器 ⭐
│ ├── json_formatters.py # JSON 格式化(middle.json, page.json)
│ ├── markdown_generator.py # Markdown 生成器
│ ├── html_generator.py # HTML 生成器
│ ├── visualization_utils.py # 可视化工具(layout/OCR 图片)
│ └── normalize_financial_numbers.py # 金额数字标准化
│
├── main_v2.py # 命令行入口 ⭐
└── 模型统一框架.md # 本文档
# 处理单个 PDF 文件
python main_v2.py -i document.pdf -c config/bank_statement_yusys_v2.yaml
# 处理图片目录
python main_v2.py -i ./images/ -c config/bank_statement_yusys_v2.yaml
# 开启 debug 模式(输出可视化图片)
python main_v2.py -i doc.pdf -c config/bank_statement_yusys_v2.yaml --debug
# 指定输出目录
python main_v2.py -i doc.pdf -c config/bank_statement_yusys_v2.yaml -o ./my_output/
from core.pipeline_manager_v2 import EnhancedDocPipeline
from utils import OutputFormatterV2
# 初始化流水线
with EnhancedDocPipeline("config/bank_statement_yusys_v2.yaml") as pipeline:
# 处理文档
results = pipeline.process_document("document.pdf")
# 保存结果
formatter = OutputFormatterV2("./output")
output_paths = formatter.save_results(results, {
'save_json': True,
'save_markdown': True,
'save_html': True,
'save_layout_image': True, # debug
'save_ocr_image': True, # debug
'normalize_numbers': True, # 金额标准化
})
| 输出文件 | 说明 |
|---|---|
{doc}_middle.json |
MinerU 标准格式 JSON |
{doc}_page_001.json |
每页独立 JSON(包含单元格坐标) |
{doc}.md |
完整文档 Markdown |
{doc}_page_001.md |
每页独立 Markdown(带坐标注释) |
tables/*.html |
表格 HTML 文件(带 data-bbox 坐标) |
images/ |
提取的图片元素 |
{doc}_page_001_layout.png |
Layout 可视化图片(debug 模式) |
{doc}_page_001_ocr.png |
OCR 可视化图片(debug 模式) |
*_original.* |
标准化前的原始文件(如有修改) |
配置文件采用 YAML 格式,主要配置项:
# 场景名称
scene_name: "bank_statement"
# 输入配置
input:
supported_formats: [".pdf", ".png", ".jpg", ".jpeg"]
dpi: 200 # PDF 转图片的 DPI
# 预处理(方向识别)
preprocessor:
module: "mineru"
orientation_classifier:
enabled: true # 扫描件自动开启
# 版式检测
layout_detection:
module: "docling" # 可选: "mineru", "paddle", "docling"
model_name: "docling-layout-old"
model_dir: "ds4sd/docling-layout-old" # HuggingFace 模型仓库
device: "cpu"
conf: 0.3
# VL 识别(表格、公式)
vl_recognition:
module: "paddle" # 可选: "mineru", "paddle"
backend: "http-client"
server_url: "http://xxx:8110"
table_recognition:
return_cells_coordinate: true
# OCR 识别
ocr_recognition:
module: "mineru"
language: "ch"
# 输出配置
output:
create_subdir: false # 是否创建子目录
save_json: true
save_markdown: true
save_html: true
save_layout_image: false # debug 模式开启
save_ocr_image: false # debug 模式开启
normalize_numbers: true # 金额数字标准化
基于 HuggingFace transformers 的 RT-DETR 模型。
layout_detection:
module: "docling"
model_name: "docling-layout-old"
model_dir: "ds4sd/docling-layout-old"
支持的模型:
ds4sd/docling-layout-oldds4sd/docling-layout-heronds4sd/docling-layout-egret-mediumds4sd/docling-layout-egret-large基于 ONNX Runtime 的 PaddleX 布局检测器。
layout_detection:
module: "paddle"
model_name: "RT-DETR-H_layout_17cls"
model_dir: "/path/to/RT-DETR-H_layout_17cls.onnx"
MinerU 内置的布局检测模型。
layout_detection:
module: "mineru"
model_name: "layout"
所有布局检测器的输出都会统一映射到 MinerU/EnhancedDocPipeline 类别体系:
| 类别分类 | 包含类别 |
|---|---|
| 文本类 (TEXT) | text, title, header, footer, page_number, ref_text, page_footnote, aside_text, ocr_text |
| 表格类 (TABLE) | table, table_body, table_caption, table_footnote |
| 图片类 (IMAGE) | image, image_body, figure, image_caption, image_footnote |
| 公式类 (EQUATION) | interline_equation, inline_equation, equation |
| 代码类 (CODE) | code, code_body, code_caption, algorithm |
| 丢弃类 (DISCARD) | abandon, discarded |
pipeline_manager_v2.py)主流水线管理器,实现完整处理流程:
layout_utils.py)OCR Span 与 Layout Block 匹配器,参考 MinerU 实现:
match_spans_to_blocks() - 将 spans 匹配到对应的 blocksmerge_spans_to_text() - 将多个 spans 合并为文本remove_duplicate_spans() - 去除重复 spanspoly_to_bbox() - 多边形坐标转 bboxelement_processors.py)元素处理器,处理不同类型的元素:
process_text_element() - 文本处理(支持 pre_matched_spans)process_table_element() - 表格处理(VLM + OCR 坐标匹配)process_image_element() - 图片处理process_equation_element() - 公式处理process_code_element() - 代码处理process_discard_element() - 丢弃元素处理(支持 pre_matched_spans)output_formatter_v2.py)统一输出格式化器:
merger)表格单元格坐标匹配器:
mineru.utils.pdf_image_tools - PDF 图像处理mineru.utils.pdf_text_tool - PDF 文本提取mineru.utils.boxbase - 边界框计算mineru.model.ocr - OCR 模型mineru.model.ori_cls - 方向分类模型merger.table_cell_matcher.TableCellMatcher - 单元格坐标匹配merger.text_matcher.TextMatcher - 文本匹配# 1. 进入 ocr_verify 目录
cd /Users/zhch158/workspace/repository.git/ocr_verify
# 2. 安装 merger 模块(可编辑模式)
pip uninstall -y merger && pip install -e .
# 3. 验证安装
python3 -c "from merger.table_cell_matcher import TableCellMatcher; print('✅ 安装成功')"
完成后,在任何 Python 文件中都可以直接导入:
from merger.table_cell_matcher import TableCellMatcher
from merger.text_matcher import TextMatcher
from merger.bbox_extractor import BBoxExtractor
/Users/zhch158/workspace/repository.git/
├── ocr_verify/ # 源项目
│ ├── setup.py # 安装配置
│ └── merger/ # 表格匹配模块
│ ├── table_cell_matcher.py # 表格单元格匹配
│ ├── text_matcher.py # 文本匹配
│ └── bbox_extractor.py # 边界框提取
│
└── MinerU/ # 目标项目
└── zhch/
└── universal_doc_parser/ # 金融文档处理框架
├── core/ # 核心处理模块
├── models/adapters/ # 模型适配器
├── utils/ # 输出工具
└── config/ # 配置文件