Files
invoice-master-poc-v2/README.md
Yaojia Wang 58bf75db68 WIP
2026-01-27 00:47:10 +01:00

795 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Invoice Master POC v2
自动发票字段提取系统 - 使用 YOLOv11 + PaddleOCR 从瑞典 PDF 发票中提取结构化数据。
## 项目概述
本项目实现了一个完整的发票字段自动提取流程:
1. **自动标注**: 利用已有 CSV 结构化数据 + OCR 自动生成 YOLO 训练标注
2. **模型训练**: 使用 YOLOv11 训练字段检测模型
3. **推理提取**: 检测字段区域 → OCR 提取文本 → 字段规范化
### 当前进度
| 指标 | 数值 |
|------|------|
| **已标注文档** | 9,738 (9,709 成功) |
| **总体字段匹配率** | 94.8% (82,604/87,121) |
**各字段匹配率:**
| 字段 | 匹配率 | 说明 |
|------|--------|------|
| supplier_accounts(Bankgiro) | 100.0% | 供应商 Bankgiro |
| supplier_accounts(Plusgiro) | 100.0% | 供应商 Plusgiro |
| Plusgiro | 99.4% | 支付 Plusgiro |
| OCR | 99.1% | OCR 参考号 |
| Bankgiro | 99.0% | 支付 Bankgiro |
| InvoiceNumber | 98.9% | 发票号码 |
| InvoiceDueDate | 95.9% | 到期日期 |
| InvoiceDate | 95.5% | 发票日期 |
| Amount | 91.3% | 金额 |
| supplier_organisation_number | 78.2% | 供应商组织号 (CSV 数据质量问题) |
## 运行环境
本项目**必须**在 **WSL + Conda** 环境中运行。
### 系统要求
| 环境 | 要求 |
|------|------|
| **WSL** | WSL 2 + Ubuntu 22.04 |
| **Conda** | Miniconda 或 Anaconda |
| **Python** | 3.10+ (通过 Conda 管理) |
| **GPU** | NVIDIA GPU + CUDA 12.x (强烈推荐) |
| **数据库** | PostgreSQL (存储标注结果) |
## 功能特点
- **双模式 PDF 处理**: 支持文本层 PDF 和扫描图 PDF
- **自动标注**: 利用已有 CSV 结构化数据自动生成 YOLO 训练数据
- **多策略字段匹配**: 精确匹配、子串匹配、规范化匹配
- **数据库存储**: 标注结果存储在 PostgreSQL支持增量处理和断点续传
- **YOLO 检测**: 使用 YOLOv11 检测发票字段区域
- **OCR 识别**: 使用 PaddleOCR v5 提取检测区域的文本
- **统一解析器**: payment_line 和 customer_number 采用独立解析器模块
- **交叉验证**: payment_line 数据与单独检测字段交叉验证,优先采用 payment_line 值
- **文档类型识别**: 自动区分 invoice (有 payment_line) 和 letter (无 payment_line)
- **Web 应用**: 提供 REST API 和可视化界面
- **增量训练**: 支持在已训练模型基础上继续训练
- **内存优化**: 支持低内存模式训练 (--low-memory)
## 支持的字段
| 类别 ID | 字段名 | 说明 |
|---------|--------|------|
| 0 | invoice_number | 发票号码 |
| 1 | invoice_date | 发票日期 |
| 2 | invoice_due_date | 到期日期 |
| 3 | ocr_number | OCR 参考号 (瑞典支付系统) |
| 4 | bankgiro | Bankgiro 号码 |
| 5 | plusgiro | Plusgiro 号码 |
| 6 | amount | 金额 |
| 7 | supplier_organisation_number | 供应商组织号 |
| 8 | payment_line | 支付行 (机器可读格式) |
| 9 | customer_number | 客户编号 |
## DPI 配置
**重要**: 系统所有组件统一使用 **150 DPI**,确保训练和推理的一致性。
DPI每英寸点数设置必须在训练和推理时保持一致否则会导致
- 检测框尺寸失配
- mAP显著下降可能从93.5%降到60-70%
- 字段漏检或误检
### 配置位置
| 组件 | 配置文件 | 配置项 |
|------|---------|--------|
| **全局常量** | `src/config.py` | `DEFAULT_DPI = 150` |
| **Web推理** | `src/web/config.py` | `ModelConfig.dpi` (导入自 `src.config`) |
| **CLI推理** | `src/cli/infer.py` | `--dpi` 默认值 = `DEFAULT_DPI` |
| **自动标注** | `src/config.py` | `AUTOLABEL['dpi'] = DEFAULT_DPI` |
| **PDF转图** | `src/web/api/v1/admin/documents.py` | 使用 `DEFAULT_DPI` |
### 使用示例
```bash
# 训练使用默认150 DPI
python -m src.cli.autolabel --dual-pool --cpu-workers 3 --gpu-workers 1
# 推理默认150 DPI与训练一致
python -m src.cli.infer -m runs/train/invoice_fields/weights/best.pt -i invoice.pdf
# 手动指定DPI仅当需要与非默认训练DPI的模型配合时
python -m src.cli.infer -m custom_model.pt -i invoice.pdf --dpi 150
```
## 安装
```bash
# 1. 进入 WSL
wsl -d Ubuntu-22.04
# 2. 创建 Conda 环境
conda create -n invoice-py311 python=3.11 -y
conda activate invoice-py311
# 3. 进入项目目录
cd /mnt/c/Users/yaoji/git/ColaCoder/invoice-master-poc-v2
# 4. 安装依赖
pip install -r requirements.txt
# 5. 安装 Web 依赖
pip install uvicorn fastapi python-multipart pydantic
```
## 快速开始
### 1. 准备数据
```
~/invoice-data/
├── raw_pdfs/
│ ├── {DocumentId}.pdf
│ └── ...
├── structured_data/
│ └── document_export_YYYYMMDD.csv
└── dataset/
└── temp/ (渲染的图片)
```
CSV 格式:
```csv
DocumentId,InvoiceDate,InvoiceNumber,InvoiceDueDate,OCR,Bankgiro,Plusgiro,Amount
3be53fd7-...,2025-12-13,100017500321,2026-01-03,100017500321,53939484,,114
```
### 2. 自动标注
```bash
# 使用双池模式 (CPU + GPU)
python -m src.cli.autolabel \
--dual-pool \
--cpu-workers 3 \
--gpu-workers 1
# 单线程模式
python -m src.cli.autolabel --workers 4
```
### 3. 训练模型
```bash
# 从预训练模型开始训练
python -m src.cli.train \
--model yolo11n.pt \
--epochs 100 \
--batch 16 \
--name invoice_fields \
--dpi 150
# 低内存模式 (适用于内存不足场景)
python -m src.cli.train \
--model yolo11n.pt \
--epochs 100 \
--name invoice_fields \
--low-memory \
--workers 4 \
--no-cache
# 从检查点恢复训练 (训练中断后)
python -m src.cli.train \
--model runs/train/invoice_fields/weights/last.pt \
--epochs 100 \
--name invoice_fields \
--resume
```
### 4. 增量训练
当添加新数据后,可以在已训练模型基础上继续训练:
```bash
# 从已训练的 best.pt 继续训练
python -m src.cli.train \
--model runs/train/invoice_yolo11n_full/weights/best.pt \
--epochs 30 \
--batch 16 \
--name invoice_yolo11n_v2 \
--dpi 150
```
**增量训练建议**:
| 场景 | 建议 |
|------|------|
| 添加少量新数据 (<20%) | 继续训练 10-30 epochs |
| 添加大量新数据 (>50%) | 继续训练 50-100 epochs |
| 修正大量标注错误 | 从头训练 |
| 添加新的字段类型 | 从头训练 |
### 5. 推理
```bash
# 命令行推理
python -m src.cli.infer \
--model runs/train/invoice_fields/weights/best.pt \
--input path/to/invoice.pdf \
--output result.json \
--gpu
# 批量推理
python -m src.cli.infer \
--model runs/train/invoice_fields/weights/best.pt \
--input invoices/*.pdf \
--output results/ \
--gpu
```
**推理结果包含**:
- `fields`: 提取的字段值 (InvoiceNumber, Amount, payment_line, customer_number 等)
- `confidence`: 各字段的置信度
- `document_type`: 文档类型 ("invoice" 或 "letter")
- `cross_validation`: payment_line 交叉验证结果 (如果有)
### 6. Web 应用
**在 WSL 环境中启动**:
```bash
# 方法 1: 从 Windows PowerShell 启动 (推荐)
wsl bash -c "source ~/miniconda3/etc/profile.d/conda.sh && conda activate invoice-py311 && cd /mnt/c/Users/yaoji/git/ColaCoder/invoice-master-poc-v2 && python run_server.py --port 8000"
# 方法 2: 在 WSL 内启动
conda activate invoice-py311
cd /mnt/c/Users/yaoji/git/ColaCoder/invoice-master-poc-v2
python run_server.py --port 8000
# 方法 3: 使用启动脚本
./start_web.sh
```
**服务启动后**:
- 访问 **http://localhost:8000** 使用 Web 界面
- 服务会自动加载模型 `runs/train/invoice_fields/weights/best.pt`
- GPU 默认启用,置信度阈值 0.5
#### Web API 端点
| 方法 | 端点 | 描述 |
|------|------|------|
| GET | `/` | Web UI 界面 |
| GET | `/api/v1/health` | 健康检查 |
| POST | `/api/v1/infer` | 上传文件并推理 |
| GET | `/api/v1/results/{filename}` | 获取可视化图片 |
#### API 响应格式
```json
{
"status": "success",
"result": {
"document_id": "abc123",
"document_type": "invoice",
"fields": {
"InvoiceNumber": "12345",
"Amount": "1234.56",
"payment_line": "# 94228110015950070 # > 48666036#14#",
"customer_number": "UMJ 436-R"
},
"confidence": {
"InvoiceNumber": 0.95,
"Amount": 0.92
},
"cross_validation": {
"is_valid": true,
"ocr_match": true,
"amount_match": true
}
}
}
```
## 训练配置
### YOLO 训练参数
```bash
python -m src.cli.train [OPTIONS]
Options:
--model, -m 基础模型 (默认: yolo11n.pt)
--epochs, -e 训练轮数 (默认: 100)
--batch, -b 批大小 (默认: 16)
--imgsz 图像尺寸 (默认: 1280)
--dpi PDF 渲染 DPI (默认: 150)
--name 训练名称
--limit 限制文档数 (用于测试)
--device 设备 (0=GPU, cpu)
--resume 从检查点恢复训练
--low-memory 启用低内存模式 (batch=8, workers=4, no-cache)
--workers 数据加载 worker 数 (默认: 8)
--cache 缓存图像到内存
```
### 训练最佳实践
1. **禁用翻转增强** (文本检测):
```python
fliplr=0.0, flipud=0.0
```
2. **使用 Early Stopping**:
```python
patience=20
```
3. **启用 AMP** (混合精度训练):
```python
amp=True
```
4. **保存检查点**:
```python
save_period=10
```
### 训练结果示例
**最新训练结果** (100 epochs, 2026-01-22):
| 指标 | 值 |
|------|-----|
| **mAP@0.5** | 93.5% |
| **mAP@0.5-0.95** | 83.0% |
| **训练集** | ~10,000 张标注图片 |
| **字段类型** | 10 个字段 (新增 payment_line, customer_number) |
| **模型位置** | `runs/train/invoice_fields/weights/best.pt` |
**各字段检测性能**:
- 发票基础信息 (InvoiceNumber, InvoiceDate, InvoiceDueDate): >95% mAP
- 支付信息 (OCR, Bankgiro, Plusgiro, Amount): >90% mAP
- 组织信息 (supplier_org_number, customer_number): >85% mAP
- 支付行 (payment_line): >80% mAP
**模型文件**:
```
runs/train/invoice_fields/weights/
├── best.pt # 最佳模型 (mAP@0.5 最高) ⭐ 推荐用于生产
└── last.pt # 最后检查点 (用于继续训练)
```
> 注:目前仍在持续标注更多数据,预计最终将有 25,000+ 张标注图片用于训练。
## 项目结构
```
invoice-master-poc-v2/
├── src/
│ ├── cli/ # 命令行工具
│ │ ├── autolabel.py # 自动标注
│ │ ├── train.py # 模型训练
│ │ ├── infer.py # 推理
│ │ └── serve.py # Web 服务器
│ ├── pdf/ # PDF 处理
│ │ ├── extractor.py # 文本提取
│ │ ├── renderer.py # 图像渲染
│ │ └── detector.py # 类型检测
│ ├── ocr/ # PaddleOCR 封装
│ │ └── machine_code_parser.py # 机器可读付款行解析器
│ ├── normalize/ # 字段规范化
│ ├── matcher/ # 字段匹配
│ ├── yolo/ # YOLO 相关
│ │ ├── annotation_generator.py
│ │ └── db_dataset.py
│ ├── inference/ # 推理管道
│ │ ├── pipeline.py # 主推理流程
│ │ ├── yolo_detector.py # YOLO 检测
│ │ ├── field_extractor.py # 字段提取
│ │ ├── payment_line_parser.py # 支付行解析器
│ │ └── customer_number_parser.py # 客户编号解析器
│ ├── processing/ # 多池处理架构
│ │ ├── worker_pool.py
│ │ ├── cpu_pool.py
│ │ ├── gpu_pool.py
│ │ ├── task_dispatcher.py
│ │ └── dual_pool_coordinator.py
│ ├── web/ # Web 应用
│ │ ├── app.py # FastAPI 应用入口
│ │ ├── routes.py # API 路由
│ │ ├── services.py # 业务逻辑
│ │ └── schemas.py # 数据模型
│ ├── utils/ # 工具模块
│ │ ├── text_cleaner.py # 文本清理
│ │ ├── validators.py # 字段验证
│ │ ├── fuzzy_matcher.py # 模糊匹配
│ │ └── ocr_corrections.py # OCR 错误修正
│ └── data/ # 数据处理
├── tests/ # 测试文件
│ ├── ocr/ # OCR 模块测试
│ │ └── test_machine_code_parser.py
│ ├── inference/ # 推理模块测试
│ ├── normalize/ # 规范化模块测试
│ └── utils/ # 工具模块测试
├── docs/ # 文档
│ ├── REFACTORING_SUMMARY.md
│ └── TEST_COVERAGE_IMPROVEMENT.md
├── config.py # 配置文件
├── run_server.py # Web 服务器启动脚本
├── runs/ # 训练输出
│ └── train/
│ └── invoice_fields/
│ └── weights/
│ ├── best.pt # 最佳模型
│ └── last.pt # 最后检查点
└── requirements.txt
```
## 多池处理架构
项目使用 CPU + GPU 双池架构处理不同类型的 PDF
```
┌─────────────────────────────────────────────────────┐
│ DualPoolCoordinator │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ CPU Pool │ │ GPU Pool │ │
│ │ (3 workers) │ │ (1 worker) │ │
│ │ │ │ │ │
│ │ Text PDFs │ │ Scanned PDFs │ │
│ │ ~50-87 it/s │ │ ~1-2 it/s │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ TaskDispatcher: 根据 PDF 类型分配任务 │
└─────────────────────────────────────────────────────┘
```
### 关键设计
- **spawn 启动方式**: 兼容 CUDA 多进程
- **as_completed()**: 无死锁结果收集
- **进程初始化器**: 每个 worker 加载一次模型
- **协调器持久化**: 跨 CSV 文件复用 worker 池
## 配置文件
### config.py
```python
# 数据库配置
DATABASE = {
'host': '192.168.68.31',
'port': 5432,
'database': 'docmaster',
'user': 'docmaster',
'password': '******',
}
# 路径配置
PATHS = {
'csv_dir': '~/invoice-data/structured_data',
'pdf_dir': '~/invoice-data/raw_pdfs',
'output_dir': '~/invoice-data/dataset',
}
```
## CLI 命令参考
### autolabel
```bash
python -m src.cli.autolabel [OPTIONS]
Options:
--csv, -c CSV 文件路径 (支持 glob)
--pdf-dir, -p PDF 文件目录
--output, -o 输出目录
--workers, -w 单线程模式 worker 数 (默认: 4)
--dual-pool 启用双池模式
--cpu-workers CPU 池 worker 数 (默认: 3)
--gpu-workers GPU 池 worker 数 (默认: 1)
--dpi 渲染 DPI (默认: 150)
--limit, -l 限制处理文档数
```
### train
```bash
python -m src.cli.train [OPTIONS]
Options:
--model, -m 基础模型路径
--epochs, -e 训练轮数 (默认: 100)
--batch, -b 批大小 (默认: 16)
--imgsz 图像尺寸 (默认: 1280)
--dpi PDF 渲染 DPI (默认: 150)
--name 训练名称
--limit 限制文档数
```
### infer
```bash
python -m src.cli.infer [OPTIONS]
Options:
--model, -m 模型路径
--input, -i 输入 PDF/图像
--output, -o 输出 JSON 路径
--confidence 置信度阈值 (默认: 0.5)
--dpi 渲染 DPI (默认: 150, 必须与训练DPI一致)
--gpu 使用 GPU
```
### serve
```bash
python run_server.py [OPTIONS]
Options:
--host 绑定地址 (默认: 0.0.0.0)
--port 端口 (默认: 8000)
--model, -m 模型路径
--confidence 置信度阈值 (默认: 0.3)
--dpi 渲染 DPI (默认: 150)
--no-gpu 禁用 GPU
--reload 开发模式自动重载
--debug 调试模式
```
## Python API
```python
from src.inference.pipeline import InferencePipeline
# 初始化
pipeline = InferencePipeline(
model_path='runs/train/invoice_fields/weights/best.pt',
confidence_threshold=0.25,
use_gpu=True,
dpi=150,
enable_fallback=True
)
# 处理 PDF
result = pipeline.process_pdf('invoice.pdf')
# 处理图片
result = pipeline.process_image('invoice.png')
# 获取结果
print(result.fields)
# {
# 'InvoiceNumber': '12345',
# 'Amount': '1234.56',
# 'payment_line': '# 94228110015950070 # > 48666036#14#',
# 'customer_number': 'UMJ 436-R',
# ...
# }
print(result.confidence) # {'InvoiceNumber': 0.95, 'Amount': 0.92, ...}
print(result.to_json()) # JSON 格式输出
# 访问交叉验证结果
if result.cross_validation:
print(f"OCR match: {result.cross_validation.ocr_match}")
print(f"Amount match: {result.cross_validation.amount_match}")
print(f"Details: {result.cross_validation.details}")
```
### 统一解析器使用
```python
from src.inference.payment_line_parser import PaymentLineParser
from src.inference.customer_number_parser import CustomerNumberParser
# Payment Line 解析
parser = PaymentLineParser()
result = parser.parse("# 94228110015950070 # 15658 00 8 > 48666036#14#")
print(f"OCR: {result.ocr_number}")
print(f"Amount: {result.amount}")
print(f"Account: {result.account_number}")
# Customer Number 解析
parser = CustomerNumberParser()
result = parser.parse("Said, Shakar Umj 436-R Billo")
print(f"Customer Number: {result}") # "UMJ 436-R"
```
## 测试
### 测试统计
| 指标 | 数值 |
|------|------|
| **测试总数** | 688 |
| **通过率** | 100% |
| **整体覆盖率** | 37% |
### 关键模块覆盖率
| 模块 | 覆盖率 | 测试数 |
|------|--------|--------|
| `machine_code_parser.py` | 65% | 79 |
| `payment_line_parser.py` | 85% | 45 |
| `customer_number_parser.py` | 90% | 32 |
### 运行测试
```bash
# 运行所有测试
wsl bash -c "source ~/miniconda3/etc/profile.d/conda.sh && conda activate invoice-py311 && cd /mnt/c/Users/yaoji/git/ColaCoder/invoice-master-poc-v2 && pytest"
# 运行并查看覆盖率
wsl bash -c "source ~/miniconda3/etc/profile.d/conda.sh && conda activate invoice-py311 && cd /mnt/c/Users/yaoji/git/ColaCoder/invoice-master-poc-v2 && pytest --cov=src --cov-report=term-missing"
# 运行特定模块测试
wsl bash -c "source ~/miniconda3/etc/profile.d/conda.sh && conda activate invoice-py311 && cd /mnt/c/Users/yaoji/git/ColaCoder/invoice-master-poc-v2 && pytest tests/ocr/test_machine_code_parser.py -v"
```
### 测试结构
```
tests/
├── ocr/
│ ├── test_machine_code_parser.py # 支付行解析 (79 tests)
│ └── test_ocr_engine.py # OCR 引擎测试
├── inference/
│ ├── test_payment_line_parser.py # 支付行解析器
│ └── test_customer_number_parser.py # 客户编号解析器
├── normalize/
│ └── test_normalizers.py # 字段规范化
└── utils/
└── test_validators.py # 字段验证
```
## 开发状态
**已完成功能**:
- [x] 文本层 PDF 自动标注
- [x] 扫描图 OCR 自动标注
- [x] 多策略字段匹配 (精确/子串/规范化)
- [x] PostgreSQL 数据库存储 (断点续传)
- [x] 信号处理和超时保护
- [x] YOLO 训练 (93.5% mAP@0.5, 10 个字段)
- [x] 推理管道
- [x] 字段规范化和验证
- [x] Web 应用 (FastAPI + REST API)
- [x] 增量训练支持
- [x] 内存优化训练 (--low-memory, --resume)
- [x] Payment Line 解析器 (统一模块)
- [x] Customer Number 解析器 (统一模块)
- [x] Payment Line 交叉验证 (OCR, Amount, Account)
- [x] 文档类型识别 (invoice/letter)
- [x] 单元测试覆盖 (688 tests, 37% coverage)
**进行中**:
- [ ] 完成全部 25,000+ 文档标注
- [ ] 多源融合增强 (Multi-source fusion)
- [ ] OCR 错误修正集成
- [ ] 提升测试覆盖率到 60%+
**计划中**:
- [ ] 表格 items 提取
- [ ] 模型量化部署 (ONNX/TensorRT)
- [ ] 多语言支持扩展
## 关键技术特性
### 1. Payment Line 交叉验证
瑞典发票的 payment_line (支付行) 包含完整的支付信息OCR 参考号、金额、账号。我们实现了交叉验证机制:
```
Payment Line: # 94228110015950070 # 15658 00 8 > 48666036#14#
↓ ↓ ↓
OCR Number Amount Bankgiro Account
```
**验证流程**:
1. 从 payment_line 提取 OCR、Amount、Account
2. 与单独检测的字段对比验证
3. **payment_line 值优先** - 如有不匹配,采用 payment_line 的值
4. 返回验证结果和详细信息
**优势**:
- 提高数据准确性 (payment_line 是机器可读格式,更可靠)
- 发现 OCR 或检测错误
- 为数据质量提供信心指标
### 2. 统一解析器架构
采用独立解析器模块处理复杂字段:
**PaymentLineParser**:
- 解析瑞典标准支付行格式
- 提取 OCR、Amount (包含 Kronor + Öre)、Account + Check digits
- 支持多种变体格式
**CustomerNumberParser**:
- 支持多种瑞典客户编号格式 (`UMJ 436-R`, `JTY 576-3`, `FFL 019N`)
- 从混合文本中提取 (如地址行中的客户编号)
- 大小写不敏感,输出统一大写格式
**优势**:
- 代码模块化、可测试
- 易于扩展新格式
- 统一的解析逻辑,减少重复代码
### 3. 文档类型自动识别
根据 payment_line 字段自动判断文档类型:
- **invoice**: 包含 payment_line 的发票文档
- **letter**: 不含 payment_line 的信函文档
这个特性帮助下游系统区分处理流程。
### 4. 低内存模式训练
支持在内存受限环境下训练:
```bash
python -m src.cli.train --low-memory
```
自动调整:
- batch size: 16 → 8
- workers: 8 → 4
- cache: disabled
- 推荐用于 GPU 内存 < 8GB 或系统内存 < 16GB 的场景
### 5. 断点续传训练
训练中断后可从检查点恢复:
```bash
python -m src.cli.train --resume --model runs/train/invoice_fields/weights/last.pt
```
## 技术栈
| 组件 | 技术 |
|------|------|
| **目标检测** | YOLOv11 (Ultralytics) |
| **OCR 引擎** | PaddleOCR v5 (PP-OCRv5) |
| **PDF 处理** | PyMuPDF (fitz) |
| **数据库** | PostgreSQL + psycopg2 |
| **Web 框架** | FastAPI + Uvicorn |
| **深度学习** | PyTorch + CUDA 12.x |
## 常见问题
**Q: 为什么必须在 WSL 环境运行?**
A: PaddleOCR 和某些依赖在 Windows 原生环境存在兼容性问题。WSL 提供完整的 Linux 环境,确保所有依赖正常工作。
**Q: 训练过程中出现 OOM (内存不足) 错误怎么办?**
A: 使用 `--low-memory` 模式,或手动调整 `--batch` 和 `--workers` 参数。
**Q: payment_line 和单独检测字段不匹配时怎么处理?**
A: 系统默认优先采用 payment_line 的值,因为 payment_line 是机器可读格式,通常更准确。验证结果会记录在 `cross_validation` 字段中。
**Q: 如何添加新的字段类型?**
A:
1. 在 `src/inference/constants.py` 添加字段定义
2. 在 `field_extractor.py` 添加规范化方法
3. 重新生成标注数据
4. 从头训练模型
**Q: 可以用 CPU 训练吗?**
A: 可以,但速度会非常慢 (慢 10-50 倍)。强烈建议使用 GPU 训练。
## 许可证
MIT License