|
|
1 settimana fa | |
|---|---|---|
| .vscode | 2 mesi fa | |
| batch_ocr | 1 settimana fa | |
| comparator | 1 settimana fa | |
| config | 1 settimana fa | |
| image | 2 mesi fa | |
| image_edit | 2 mesi fa | |
| merger | 1 settimana fa | |
| ocr_vlm_verify | 2 mesi fa | |
| streamlit_test | 1 mese fa | |
| test | 1 mese fa | |
| .env.example | 2 mesi fa | |
| README.md | 1 settimana fa | |
| compare_ocr_results-算法.md | 1 mese fa | |
| compare_use_unified_diff.py | 1 mese fa | |
| config_manager.py | 1 settimana fa | |
| normalize_financial_numbers.py | 1 mese fa | |
| ocr_by_vlm.py | 1 mese fa | |
| ocr_validator_file_utils.py | 1 mese fa | |
| ocr_validator_layout.py | 1 mese fa | |
| ocr_validator_utils.py | 1 settimana fa | |
| run_streamlit_validator.py | 2 mesi fa | |
| streamlit_ocr_validator.py | 1 settimana fa | |
| streamlit_validator_core.py | 1 settimana fa | |
| streamlit_validator_cross.py | 4 settimane fa | |
| streamlit_validator_result.py | 1 settimana fa | |
| streamlit_validator_table.py | 1 mese fa | |
| streamlit_validator_ui.py | 1 settimana fa | |
| styles.css | 2 mesi fa | |
| 图片操作说明.md | 2 mesi fa |
一个功能强大的 OCR 识别与验证系统,集成了多种 OCR 工具支持、智能交叉验证、可视化校验和表格数据分析功能,专为财务报表、数据表格等复杂文档设计。
standard)flow_list)- 支持表头位置智能检测table_amount)- 严重度:hightable_datetime)- 严重度:mediumtable_text)- 严重度:low/medium(根据相似度)# 创建 conda 环境
conda create -n py312 python=3.12 -y
conda activate py312
# 克隆项目
git clone https://gitee.com/zhch158_admin/ocr_verify.git
cd ocr_verify
# 安装依赖
pip install -r requirements.txt
# 或手动安装核心依赖
pip install streamlit plotly pandas pillow numpy opencv-python openpyxl \
beautifulsoup4 pyyaml fuzzywuzzy python-Levenshtein
编辑配置文件(详见 config/README.md):
config/global.yaml)data_sources:
- 德_内蒙古银行照.yaml
- 对公_招商银行图.yaml
- A用户_单元格扫描流水.yaml
- B用户_扫描流水.yaml
- 至远彩色_2023年报.yaml
config/B用户_扫描流水.yaml)document:
name: "B用户_扫描流水"
base_dir: "/Users/zhch158/workspace/data/流水分析/B用户_扫描流水"
ocr_results:
# PPStructV3
- tool: "ppstructv3"
result_dir: "ppstructurev3_client_results"
image_dir: "ppstructurev3_client_results/{{name}}"
description: "PPStructV3 图片合成结果"
enabled: true
# PaddleOCR-VL
- tool: "paddleocr_vl"
result_dir: "paddleocr_vl_results"
image_dir: "paddleocr_vl_results/{{name}}"
description: "PaddleOCR VLM 图片合成结果"
enabled: true
# MinerU
- tool: "mineru"
result_dir: "mineru_vllm_results"
image_dir: "mineru_vllm_results/{{name}}"
description: "MinerU 图片合成结果"
enabled: true
# Dots OCR
- tool: "dots_ocr"
result_dir: "dotsocr_vllm_results"
image_dir: "dotsocr_vllm_results/{{name}}"
description: "Dots OCR 图片合成结果"
enabled: true
配置说明:
document.name:项目名称base_dir:项目根目录(绝对路径)ocr_results:OCR 工具结果配置数组
tool:工具标识(ppstructv3 / paddleocr_vl / mineru / dots_ocr)result_dir:结果目录(相对于 base_dir)image_dir:图像目录(支持 {{name}} 模板变量)description:工具描述enabled:是否启用(true / false)详细配置说明见 config/README.md
# 启动 Streamlit 应用
python -m streamlit run streamlit_ocr_validator.py
# 或使用启动脚本
python run_streamlit_validator.py
功能模块:
使用 comparator/compare_ocr_results.py 进行命令行对比(详见 comparator/README.md):
# 基本对比
python comparator/compare_ocr_results.py file1.md file2.md
# 使用流水表格模式(智能表头检测 + 多层表头识别)
python comparator/compare_ocr_results.py file1.md file2.md \
--table-mode flow_list \
--similarity-algorithm ratio \
-o output/comparison_result \
-f both
# 资产负债表对比(自动识别多层表头)
python comparator/compare_ocr_results.py balance_sheet1.md balance_sheet2.md \
--table-mode flow_list \
-o balance_sheet_comparison
参数说明:
-o, --output:输出文件名(不含扩展名)-f, --format:输出格式(json、markdown、both)--table-mode:表格比对模式
standard:标准表格(结构固定)flow_list:流水表格(智能表头检测、支持多层表头)--similarity-algorithm:相似度算法
ratio:标准相似度partial_ratio:部分匹配token_sort_ratio:排序后匹配token_set_ratio:集合匹配--ignore-images:忽略图片内容对比详细文档:参见 comparator/README.md
合并不同 OCR 工具的识别结果,提升准确性(详见 merger/README.md):
# 合并 MinerU 和 PaddleOCR 结果
python merger/merge_mineru_paddle_ocr.py \
--mineru-dir /path/to/mineru/output \
--paddle-dir /path/to/paddleocr/output \
--output-dir /path/to/merged/output
# 合并 PaddleOCR-VL 和 PaddleOCR 结果
python merger/merge_paddleocr_vl_paddleocr.py \
--paddleocr-vl-dir /path/to/paddleocr_vl/output \
--paddle-dir /path/to/paddleocr/output \
--output-dir /path/to/merged/output
# 合并 Dots OCR 和 PaddleOCR 结果
python merger/merge_dotsocr_paddleocr.py \
--dotsocr-dir /path/to/dotsocr/output \
--paddle-dir /path/to/paddleocr/output \
--output-dir /path/to/merged/output
合并策略:
详细文档:参见 merger/README.md
批量处理 PDF 文档并合并 OCR 结果(详见 batch_ocr/README.md):
# 批量处理 PDF 列表
python batch_ocr/batch_process_pdf.py \
--config batch_ocr/processor_configs.yaml \
--pdf-list batch_ocr/pdf_list.txt
# 批量合并 OCR 结果
python batch_ocr/batch_merge_results.py \
--config batch_ocr/processor_configs.yaml \
--pdf-list batch_ocr/pdf_list.txt \
--merge-mode mineru_paddle
配置文件示例 (processor_configs.yaml):
processors:
mineru:
command: "magic-pdf"
args:
- "-p"
- "{pdf_path}"
- "-o"
- "{output_dir}"
output_structure: "auto/{pdf_name}/auto"
paddleocr:
command: "paddleocr"
args:
- "--image_dir"
- "{image_dir}"
详细文档:参见 batch_ocr/README.md
使用 normalize_financial_numbers.py:
from normalize_financial_numbers import normalize_financial_numbers, normalize_json_file
# 标准化文本中的数字
text = "2023年净利润为28,239,305.48元"
normalized = normalize_financial_numbers(text)
# 输出: "2023年净利润为28,239,305.48元"
# 批量标准化 JSON 文件
normalize_json_file("input.json", "output.json")
ocr_verify/
├── streamlit_ocr_validator.py # 主应用入口
├── streamlit_validator_core.py # 核心验证器类
├── streamlit_validator_ui.py # UI 组件
├── streamlit_validator_table.py # 表格处理
├── streamlit_validator_cross.py # 交叉验证
├── streamlit_validator_result.py # 结果展示
├── ocr_validator_layout.py # 布局管理
├── ocr_validator_utils.py # 工具函数
├── ocr_validator_file_utils.py # 文件处理
├── normalize_financial_numbers.py # 数字标准化
├── styles.css # 样式文件
├── requirements.txt # 依赖列表
├── config/ # 配置文件目录 ✨
│ ├── global.yaml # 全局配置
│ ├── 至远彩色_2023年报.yaml # 年报类项目配置
│ ├── A用户_单元格扫描流水.yaml # 流水表格配置
│ ├── B用户_扫描流水.yaml # 流水表格配置
│ ├── 德_内蒙古银行照.yaml # 银行流水配置
│ ├── 对公_招商银行图.yaml # 银行流水配置
│ └── README.md # 配置文档 ✨
├── comparator/ # OCR 结果对比模块
│ ├── compare_ocr_results.py # 命令行对比工具
│ ├── ocr_comparator.py # 核心对比器
│ ├── table_comparator.py # 表格对比器(✨ 支持多层表头)
│ ├── paragraph_comparator.py # 段落对比器
│ ├── similarity_calculator.py # 相似度计算
│ ├── data_type_detector.py # 数据类型检测
│ ├── content_extractor.py # 内容提取器
│ ├── text_processor.py # 文本处理器
│ ├── report_generator.py # 报告生成器
│ └── README.md # 对比模块文档
├── merger/ # OCR 结果合并模块
│ ├── merge_mineru_paddle_ocr.py # MinerU + PaddleOCR 合并
│ ├── merge_paddleocr_vl_paddleocr.py # PaddleOCR-VL + PaddleOCR 合并
│ ├── merge_dotsocr_paddleocr.py # Dots OCR + PaddleOCR 合并
│ ├── merger_core.py # 合并核心逻辑
│ ├── text_matcher.py # 文本匹配器(fazz partial_ratio算法)
│ ├── bbox_extractor.py # 坐标提取器
│ ├── data_processor.py # 数据处理器
│ ├── markdown_generator.py # Markdown 生成器
│ ├── unified_output_converter.py # 统一输出转换器
│ └── README.md # 合并模块文档
├── batch_ocr/ # 批量处理模块
│ ├── batch_process_pdf.py # 批量 PDF 处理
│ ├── batch_merge_results.py # 批量结果合并
│ ├── processor_configs.yaml # 处理器配置
│ ├── pdf_list.txt # PDF 列表
│ └── README.md # 批量处理文档
├── output/ # 输出目录
│ └── pre_validation/ # 交叉验证结果
├── .streamlit/ # Streamlit 配置
│ └── config.toml # Streamlit 设置
└── README.md # 项目总文档(本文件)
数据源选择
批量验证
差异分析
结果展示
standard)flow_list) ✨智能表头检测:
# 自动检测表头位置(支持多层表头)
header_row_idx = detect_table_header_row(table)
# 检测策略:
# 1. 关键词匹配(日期、金额、余额、资产、负债等)
# 2. 下一行验证(数据行/分类行)
# 3. 多层表头识别(资产负债表等)
✨ 新增:多层表头识别
针对资产负债表等特殊表格:
# 示例表格结构:
# 第1行:['资产', '期末余额', '期初余额', '负债及所有者权益', '期末余额', '期初余额'] ← 总表头
# 第2行:['流动资产:', '', '', '流动负债:', '', ''] ← 分类标题(分类行)
# 第3行:['货币资金', '28,239,305.48', '68,162,260.60', ...] ← 数据行
def _is_category_row(row):
"""识别分类行(如"流动资产:")"""
patterns = [
r'.*:$', # 以冒号结尾
]
# 返回 True 表示是分类行
# 评分调整:
# - 数据行:+0.2 分
# - 分类行:+0.1 分(新增)
列类型检测:
numeric:数字金额datetime:日期时间text_number:文本型数字(如票据号)text:普通文本✨ 差异严重度改进:
# 基础严重度(由单元格对比决定)
base_severity = {
'table_amount': 'high', # 金额差异
'table_datetime': 'medium', # 日期差异
'table_text': 'low/medium' # 文本差异(根据相似度)
}
# 列类型冲突自动提升
if col_idx in mismatched_columns:
if base_severity != 'high':
final_severity = 'high' # 提升到 high
适用场景:
智能匹配两个文件中的表格,支持:
内容特征相似度 (20%)
# 表格匹配示例
matches = find_matching_tables(tables1, tables2)
# 输出: [(0, 0, 95.2), (1, 1, 87.3)]
# 格式: (文件1表格索引, 文件2表格索引, 相似度%)
# 表格内容:优先 MinerU(VLM 更准确)
# 表格坐标:使用 PaddleOCR 全局 OCR 坐标(更精确)
merged_result = merge_mineru_paddleocr(mineru_json, paddle_json)
# 表格内容:优先 PaddleOCR-VL
# 表格坐标:使用 PaddleOCR 全局 OCR 坐标
merged_result = merge_paddleocr_vl_paddleocr(vl_json, paddle_json)
# 表格内容:优先 Dots OCR
# 表格坐标:使用 PaddleOCR 全局 OCR 坐标
merged_result = merge_dotsocr_paddleocr(dots_json, paddle_json)
{
"differences": [
{
"type": "table_amount",
"position": "第15行第5列",
"file1_value": "15.00",
"file2_value": "15,00",
"description": "金额不一致: 15.00 vs 15,00",
"severity": "high",
"column_name": "金额",
"column_type": "numeric",
"row_index": 15,
"col_index": 4
},
{
"type": "table_header_position",
"position": "表头位置",
"file1_value": "第1行",
"file2_value": "第2行",
"description": "表头位置不一致: 文件1在第1行,文件2在第2行",
"severity": "high"
},
{
"type": "table_text",
"position": "第20行第3列",
"file1_value": "流动资产",
"file2_value": "流动 资产",
"description": "文本不一致: 流动资产 vs 流动 资产 [列类型冲突]",
"severity": "high",
"column_type_mismatch": true
}
],
"statistics": {
"total_differences": 42,
"table_differences": 35,
"amount_differences": 8,
"datetime_differences": 3,
"text_differences": 24,
"paragraph_differences": 7,
"critical_severity": 2,
"high_severity": 11,
"medium_severity": 17,
"low_severity": 12
}
}
# OCR结果对比报告
## 统计信息
- 总差异数量: **42**
- 表格差异: **35**
- 金额差异: **8** (严重度: high)
- 日期差异: **3** (严重度: medium)
- 文本差异: **24** (严重度: low/medium)
- 列类型冲突: **3** (严重度提升至: high)
- 段落差异: **7**
## 差异详情(按严重度分类)
### ❌ 严重差异 (Critical)
| 序号 | 位置 | 类型 | 原OCR结果 | 验证结果 | 描述 |
|------|------|------|-----------|----------|------|
| 1 | 表格列类型 | table_header_critical | 5列类型不一致 | 共10列 | 列类型差异过大 (50%) |
### ⚠️ 高优先级差异 (High)
| 序号 | 位置 | 类型 | 原OCR结果 | 验证结果 | 描述 |
|------|------|------|-----------|----------|------|
| 1 | 第15行第5列 | table_amount | 15.00 | 15,00 | 金额不一致 |
| 2 | 第20行第3列 | table_text | 流动资产 | 流动 资产 | 文本不一致 [列类型冲突] |
### ℹ️ 中优先级差异 (Medium)
...
### 💡 低优先级差异 (Low)
...
项目使用 YAML 配置文件管理数据源和工具参数(详见 config/README.md)。
全局配置 (config/global.yaml):
data_sources:
- 德_内蒙古银行照.yaml
- 对公_招商银行图.yaml
- A用户_单元格扫描流水.yaml
- B用户_扫描流水.yaml
- 至远彩色_2023年报.yaml
项目配置 (config/B用户_扫描流水.yaml):
document:
name: "B用户_扫描流水"
base_dir: "/Users/zhch158/workspace/data/流水分析/B用户_扫描流水"
ocr_results:
- tool: "ppstructv3"
result_dir: "ppstructurev3_client_results"
image_dir: "ppstructurev3_client_results/{{name}}"
description: "PPStructV3 图片合成结果"
enabled: true
- tool: "mineru"
result_dir: "mineru_vllm_results"
image_dir: "mineru_vllm_results/{{name}}"
description: "MinerU 图片合成结果"
enabled: true
配置参数说明:
document.name:项目名称(用于模板变量替换)base_dir:项目根目录(绝对路径)tool:OCR 工具标识(ppstructv3 / paddleocr_vl / mineru / dots_ocr)result_dir:结果目录(相对于 base_dir)image_dir:图像目录(支持 {{name}} 模板变量)enabled:是否启用该数据源在 batch_ocr/processor_configs.yaml 中配置(详见 batch_ocr/README.md):
processors:
mineru:
command: "magic-pdf"
args:
- "-p"
- "{pdf_path}"
- "-o"
- "{output_dir}"
- "--method"
- "auto"
output_structure: "auto/{pdf_name}/auto"
paddleocr:
command: "paddleocr"
args:
- "--image_dir"
- "{image_dir}"
- "--type"
- "structure"
- "--det_model_dir"
- "models/ch_PP-OCRv4_det_infer"
- "--rec_model_dir"
- "models/ch_PP-OCRv4_rec_infer"
output_structure: "{pdf_name}/ppstructure"
merge:
mineru_paddle:
priority: "mineru" # 表格内容优先级
coordinate_source: "paddleocr" # 坐标来源
iou_threshold: 0.5 # IoU 匹配阈值
编辑 .streamlit/config.toml:
[theme]
primaryColor = "#0288d1"
backgroundColor = "#ffffff"
secondaryBackgroundColor = "#f5f5f5"
textColor = "#262730"
font = "sans serif"
[server]
maxUploadSize = 200
enableXsrfProtection = true
enableCORS = false
[browser]
gatherUsageStats = false
A: 检查配置文件中的 OCR 工具坐标参数设置(不同工具的坐标处理方式可能不同)。
A:
enabled: true 设置base_dir 和 result_dir 路径正确A:
--table-mode flow_list(智能表头检测)--similarity-algorithm token_set_ratio)A: 使用合并工具结合 PaddleOCR 的全局 OCR 坐标:
python merger/merge_mineru_paddle_ocr.py \
--mineru-dir /path/to/mineru \
--paddle-dir /path/to/paddleocr \
--output-dir /path/to/output
A: 使用 flow_list 模式,算法会自动检测多层表头:
python comparator/compare_ocr_results.py balance_sheet1.md balance_sheet2.md \
--table-mode flow_list
识别逻辑:
调试信息:
📍 检测到表头在第 1 行 (得分: 0.87)
行数对比: 10 vs 10, 相似度: 100.0%
列数对比: 6 vs 6, 相似度: 100.0%
表头位置: 文件1第1行, 文件2第1行
表头相似度: 92.5%
精确匹配: 83%, 模糊匹配: 100%, 语义匹配: 100%
A:
global.yaml 中是否正确引用了项目配置文件config/ 目录下A:
{{name}}document.name 是否已定义A:
processor_configs.yaml 配置是否正确A: 这是正常现象,列类型冲突会自动将差异严重度提升到 high:
{
"type": "table_text",
"severity": "high",
"column_type_mismatch": true,
"description": "文本不一致 [列类型冲突]"
}
建议:
merger/ 中实现合并逻辑(如需要)config/README.md 文档from comparator.ocr_comparator import OCRResultComparator
class CustomComparator(OCRResultComparator):
def compare_tables(self, table1, table2):
# 自定义对比逻辑
pass
在 ocr_validator_layout.py 中扩展:
def render_custom_mode(self, content):
# 自定义渲染逻辑
pass
感谢以下开源项目的支持:
最后更新: 2025年11月7日