# Invoice Master POC v2 自动账单信息提取系统 - 使用 YOLOv11 + PaddleOCR 从瑞典 PDF 发票中提取结构化数据。 ## 运行环境 本项目**必须**在 **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 训练数据 - **多池处理架构**: CPU 池处理文本 PDF,GPU 池处理扫描 PDF - **数据库存储**: 标注结果存储在 PostgreSQL,支持增量处理 - **YOLO 检测**: 使用 YOLOv11 检测发票字段区域 - **OCR 识别**: 使用 PaddleOCR 3.x 提取检测区域的文本 - **Web 应用**: 提供 REST API 和可视化界面 - **增量训练**: 支持在已训练模型基础上继续训练 ## 支持的字段 | 类别 ID | 字段名 | 说明 | |---------|--------|------| | 0 | invoice_number | 发票号码 | | 1 | invoice_date | 发票日期 | | 2 | invoice_due_date | 到期日期 | | 3 | ocr_number | OCR 参考号 (瑞典支付系统) | | 4 | bankgiro | Bankgiro 号码 | | 5 | plusgiro | Plusgiro 号码 | | 6 | amount | 金额 | ## 安装 ```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_yolo11n_full \ --dpi 150 ``` ### 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_yolo11n_full/weights/best.pt \ --input path/to/invoice.pdf \ --output result.json \ --gpu ``` ### 6. Web 应用 ```bash # 启动 Web 服务器 python run_server.py --port 8000 # 开发模式 (自动重载) python run_server.py --debug --reload # 禁用 GPU python run_server.py --no-gpu ``` 访问 **http://localhost:8000** 使用 Web 界面。 #### Web API 端点 | 方法 | 端点 | 描述 | |------|------|------| | GET | `/` | Web UI 界面 | | GET | `/api/v1/health` | 健康检查 | | POST | `/api/v1/infer` | 上传文件并推理 | | GET | `/api/v1/results/{filename}` | 获取可视化图片 | ## 训练配置 ### 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) ``` ### 训练最佳实践 1. **禁用翻转增强** (文本检测): ```python fliplr=0.0, flipud=0.0 ``` 2. **使用 Early Stopping**: ```python patience=20 ``` 3. **启用 AMP** (混合精度训练): ```python amp=True ``` 4. **保存检查点**: ```python save_period=10 ``` ### 训练结果示例 使用 15,571 张训练图片,100 epochs 后的结果: | 指标 | 值 | |------|-----| | **mAP@0.5** | 98.7% | | **mAP@0.5-0.95** | 87.4% | | **Precision** | 97.5% | | **Recall** | 95.5% | ## 项目结构 ``` 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 封装 │ ├── normalize/ # 字段规范化 │ ├── matcher/ # 字段匹配 │ ├── yolo/ # YOLO 相关 │ │ ├── annotation_generator.py │ │ └── db_dataset.py │ ├── inference/ # 推理管道 │ │ ├── pipeline.py │ │ ├── yolo_detector.py │ │ └── field_extractor.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 # 数据模型 │ │ └── config.py # 配置 │ └── data/ # 数据处理 ├── config.py # 配置文件 ├── run_server.py # Web 服务器启动脚本 ├── runs/ # 训练输出 │ └── train/ │ └── invoice_yolo11n_full/ │ └── 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 (默认: 300) --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 import InferencePipeline # 初始化 pipeline = InferencePipeline( model_path='runs/train/invoice_yolo11n_full/weights/best.pt', confidence_threshold=0.3, use_gpu=True, dpi=150 ) # 处理 PDF result = pipeline.process_pdf('invoice.pdf') # 处理图片 result = pipeline.process_image('invoice.png') # 获取结果 print(result.fields) # {'InvoiceNumber': '12345', 'Amount': '1234.56', ...} print(result.confidence) # {'InvoiceNumber': 0.95, 'Amount': 0.92, ...} print(result.to_json()) # JSON 格式输出 ``` ## 开发状态 - [x] 文本层 PDF 自动标注 - [x] 扫描图 OCR 自动标注 - [x] 多池处理架构 (CPU + GPU) - [x] PostgreSQL 数据库存储 - [x] YOLO 训练 (98.7% mAP@0.5) - [x] 推理管道 - [x] 字段规范化和验证 - [x] Web 应用 (FastAPI + 前端 UI) - [x] 增量训练支持 - [ ] 表格 items 处理 - [ ] 模型量化部署 ## 许可证 MIT License