Metadata-Version: 2.4
Name: paddle_onnxocr
Version: 0.2.0
Summary: paddleOCR的onnx实现
Author-email: wyy-holding <944581678@qq.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/wyy-holding/paddleONNXOCR
Project-URL: Issues, https://github.com/wyy-holding/paddleONNXOCR/issues
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: opencv-python-headless
Requires-Dist: shapely
Requires-Dist: pyclipper
Requires-Dist: onnxruntime; "openvino" not in extra
Requires-Dist: pillow
Requires-Dist: validators
Requires-Dist: aiohttp
Requires-Dist: deskew
Requires-Dist: modelscope
Requires-Dist: filetype
Requires-Dist: pdfplumber
Requires-Dist: pymupdf
Requires-Dist: aiofiles
Provides-Extra: openvino
Requires-Dist: openvino; extra == "openvino"
Dynamic: license-file

# paddleONNXOCR

[![PyPI version](https://img.shields.io/pypi/v/paddle-onnxocr.svg)](https://pypi.org/project/paddle-onnxocr/)
[![Python](https://img.shields.io/pypi/pyversions/paddle-onnxocr.svg)](https://pypi.org/project/paddle-onnxocr/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

基于 **ONNXRuntime / OpenVINO** 的高性能 OCR 推理库，完整复刻 PP-OCRv6 官方流水线（检测 / 识别 / 方向分类 / 文档矫正 / 表格 / 版面分析），**无需安装 PaddlePaddle 框架**，模型与预处理全部与官方对齐。

## 特性

- 🚀 **轻量推理**：仅依赖 onnxruntime（或 openvino），无 PaddlePaddle 框架负担，CPU 即可流畅运行
- 🎯 **官方对齐**：模型、字典、预处理 / 后处理参数均取自官方 ONNX 包内 `inference.yml`，端到端实测与官方一致
- 🔀 **双引擎**：onnxruntime（默认）与 openvino 原生推理，一条构造参数切换，结果逐位一致
- 🧩 **全功能流水线**：文本检测 → 文本行方向分类 → 识别，外加整图 deskew / UVDoc 矫正 / 文档方向分类
- 📄 **PDF 支持**：文字层直取、表格结构化、扫描页自动走 OCR
- 📊 **表格转 HTML**：有线 / 无线表格自动分类识别，输出 HTML
- 📦 **模型自动下载**：首次使用自动从 ModelScope 拉取官方 ONNX 模型
- ⚡ **异步 + 批量**：async 接口，批量推理支持并发控制

## 安装

```bash
pip install --no-cache-dir paddle-onnxocr
```

使用 OpenVINO 后端（不安装 onnxruntime，二者互斥）：

```bash
pip install --no-cache-dir paddle-onnxocr[openvino]
```

要求 Python >= 3.10。

## 快速开始

### 单张推理

```python
from paddleONNXOCR import PredictSystem
from paddleONNXOCR.predict.ocr_dataclass import OCRResult


async def main():
    async with PredictSystem() as predictor_system:
        ocr_result: OCRResult = await predictor_system.predict(
            "https://wx2.sinaimg.cn/mw690/005AKOR6ly1hvv14x3e1rj30j615hwfl.jpg"
        )
        print(ocr_result.text)          # 按阅读顺序拼接的完整文本
        for chunk in ocr_result.results:
            print(chunk.text, chunk.confidence, chunk.box)


if __name__ == '__main__':
    import asyncio
    asyncio.run(main())
```

### 批量推理

支持混用多种输入：本地路径、URL、base64、`numpy.ndarray`（BGR）、`PIL.Image`。

```python
import cv2
from PIL import Image
from paddleONNXOCR import PredictSystem


async def main():
    async with PredictSystem() as predictor_system:
        results = await predictor_system.predict_batch(
            [
                "https://wx2.sinaimg.cn/mw690/005AKOR6ly1hvv14x3e1rj30j615hwfl.jpg",
                cv2.imread("test.png"),
                Image.open("test.png"),
            ],
            max_concurrent=8,   # 最大并发数，默认 CPU 核数
        )
        for result in results:
            print(result.text)


if __name__ == '__main__':
    import asyncio
    asyncio.run(main())
```

> 批量接口内部按 `asyncio.gather(..., return_exceptions=True)` 收集结果，单张失败不会影响其他图片，异常会以 `Exception` 对象形式出现在返回列表的对应位置。

### 单例复用（长驻服务）

不适合用 `async with` 的场景（如 FastAPI lifespan），可手动管理生命周期：

```python
from paddleONNXOCR import PredictSystem

async def main():
    predictor_system = PredictSystem()
    await predictor_system.__aenter__()
    return predictor_system
# 外部拿到实例调用推理，参考 api/__init__.py 中的 lifespan
```

## 输入与颜色通道约定

`predict` / `predict_batch` 的所有输入统一按 **BGR**（OpenCV 约定）处理：

- 本地路径 / URL / base64 / PIL.Image 输入：内部自动解码并转换为 BGR
- `numpy.ndarray` 输入：原样透传，**调用方需自行保证是 BGR**（即 `cv2.imread` / `cv2.imdecode` 的输出）；
  如果手上是 PIL 风格的 RGB 数组，请先 `img = img[..., ::-1]` 翻转后再传入

> Windows 下含非 ASCII（如中文）的文件路径也支持，内部使用 `numpy.fromfile` + `cv2.imdecode` 解码。

## PDF 识别

输入为 PDF 时自动走 PDF 提取（文字层直取、表格结构化、图片 / 扫描页走 OCR），默认提取整个 PDF；
可通过 `pdf_max_pages` 只取前 N 页（`predict_batch` 中对所有 PDF 统一生效）：

```python
async with PredictSystem() as ocr:
    # 整个 PDF
    full = await ocr.predict("test.pdf")
    # 只提取前 3 页
    head = await ocr.predict("test.pdf", pdf_max_pages=3)
    for page in head.results:
        print(page.page_index, page.text)
```

## 图片表格转 HTML

自动检测图片中的表格区域，分类有线 / 无线表格后做单元格检测 + OCR，输出 `TableHtml` 列表：

```python
from paddleONNXOCR import ImageTableToHTML


async def main():
    async with ImageTableToHTML() as predictor:
        results = await predictor.predict("test.jpg")   # 注意是 async，需 await
        for i, table in enumerate(results):
            print(f"表格 {i + 1} 位置: {table.bbox}  置信度: {table.score}")
            print(table.html)


if __name__ == '__main__':
    import asyncio
    asyncio.run(main())
```

## 切换推理引擎

v0.2.0 起支持 onnxruntime / openvino 双后端，结果逐位一致（det raw 输出 max_abs=0.0000）。
`engine` 必须传 `EngineType` 枚举成员（与模型枚举风格一致），**不接受字符串**：

```python
from paddleONNXOCR import PredictSystem, EngineType

# 默认 onnxruntime
PredictSystem()

# openvino 原生推理（需 pip install paddle-onnxocr[openvino]）
PredictSystem(engine=EngineType.OPENVINO)
```

openvino 下 `providers` 含 CUDA / Tensorrt 前缀时自动映射到 GPU device，否则为 CPU。

## 更改模型

PP-OCRv6 提供 **tiny / small / medium** 三个档位（v5 的 mobile / server 已移除）：tiny 最轻、medium 最准。
注意 **tiny 档的识别模型使用独立的 6904 字精简字典**，small / medium 使用 18708 字完整字典，切换档位时字典会自动匹配。

```python
from paddleONNXOCR import PredictSystem
from paddleONNXOCR.models_enum import DetModels, RecModels

# 切换到最轻量的 tiny 档
PredictSystem(det_model_name=DetModels.TINY, rec_model_name=RecModels.TINY)

# 也可以混搭：检测用 medium，识别用 small
PredictSystem(det_model_name=DetModels.MEDIUM, rec_model_name=RecModels.SMALL)
```

### 使用自定义识别模型

非内置模型无法推断字典，必须显式传入 `charset_path`：

```python
from paddleONNXOCR import PredictSystem

PredictSystem(rec_model_path="my_rec.onnx", charset_path="my_dict.txt")
```

### 传递本地模型路径

各子模型均支持 `*_model_path` 直接指定本地 onnx 文件，跳过下载：

```python
from paddleONNXOCR import PredictSystem

PredictSystem(det_model_path="testDir/xxx.onnx")
```

### 功能开关

```python
from paddleONNXOCR import PredictSystem

PredictSystem(
    use_angle_cls=True,   # 启用文本行方向检测（180° 翻转纠正），默认 True
    use_deskew=False,     # 启用倾斜图像旋转矫正，默认 False（对齐官方 PaddleX 行为）
    use_uvdoc=False,      # 启用 UVDoc 文档图像矫正，默认 False
    use_doc_cls=True,     # 启用整图方向分类并旋转（0°/90°/180°/270°），默认 True
)
```

其他常用参数（完整说明见 `PredictSystem` 方法 docstring）：

| 参数 | 说明 | 默认 |
|---|---|---|
| `drop_score` | 识别置信度低于该值的文本块被丢弃 | `0.3` |
| `sort_boxes` | 是否按阅读顺序排序检测框 | `True` |
| `cls_thresh` | 文本行方向判定 180° 的置信度阈值 | `0.5`（与官方行为等价） |
| `det_db_thresh` / `det_db_box_thresh` / `det_db_unclip_ratio` / `det_max_candidates` | 检测后处理参数，`None` 时套用该档位模型的官方值 | `None` |
| `rec_image_shape` | 识别模型输入形状 | `"3,48,320"` |
| `model_local_dir` | 模型下载保存目录 | `"models"` |
| `pdf_table_format` | PDF 内表格的返回形式 | `"text"`（或 `"list"`） |
| `providers` / `session_options` / `executor` | onnxruntime providers / SessionOptions / 自定义线程池 | 自动选择 |

## 结果数据结构

```python
OCRResult        # 单张图片结果
├── text: str                  # 按阅读顺序拼接的完整文本
└── results: list[OCRChunkResult]

OCRChunkResult   # 单个文本块
├── text: str                  # 识别文本
├── confidence: float          # 识别置信度
├── box: list[list[float]]     # 四点坐标
├── angle: str                 # 文本行方向（"0_degree" / "180_degree"）
└── angle_confidence: float    # 方向分类置信度

PdfResult        # PDF 结果
├── text: str
└── results: list[PdfPageResult]   # 每页 page_index / text / ocr_data

TableHtml        # 表格识别结果
├── bbox: tuple[float, float, float, float]   # 表格区域坐标
├── score: float                              # 表格检测置信度
└── html: str                                 # 表格 HTML
```

## 模型下载

默认情况下，首次使用会自动从 ModelScope 下载以下模型：

```
PP-OCRv6_medium_det         -> 文本检测模型（官方仓 PaddlePaddle/PP-OCRv6_medium_det_onnx）
PP-OCRv6_medium_rec         -> 文本识别模型（官方仓 PaddlePaddle/PP-OCRv6_medium_rec_onnx）
PP-LCNet_x0_25_textline_ori -> 文本行方向检测模型（官方仓 PaddlePaddle/PP-LCNet_x0_25_textline_ori_onnx）
PP-LCNet_x1_0_doc_ori       -> 文档方向分类（官方仓 PaddlePaddle/PP-LCNet_x1_0_doc_ori_onnx）
```

除少数官方未发布 ONNX 包的模型外，全部模型均来自 PaddlePaddle 官方 ONNX 仓库
（`PaddlePaddle/<模型名>_onnx`，已覆盖：文本检测 / 识别、文本行方向、文档方向、UVDoc 矫正、
表格分类、有线 / 无线表格单元格检测、PP-DocLayout_plus-L、PP-DocBlockLayout）。
**仍走 `wyyHolding` 镜像仓的例外**：`PP-DocLayout-S/M/L` 与 `PicoDet_layout_1x_table`
（官方仅提供 Paddle 推理格式，未导出 ONNX 包）。

官方 ONNX 包内的模型文件统一命名为 `inference.onnx`，因此本地会按仓库名分目录存放，例如
`models/PP-OCRv6_medium_det_onnx/inference.onnx`。

## 日志与警告

Paddle2ONNX 导出的模型里常残留未被任何节点使用的 initializer（典型如 `p2o.pd_op.full.*`），
onnxruntime 每次加载模型都会为每一个打印一条 `Removing initializer ...` 警告。这些 initializer
无害，但会刷屏，因此库默认把 onnxruntime 的日志级别设为 `3`（只输出 ERROR）。

需要排查 onnxruntime 问题时，用环境变量调回即可（0=VERBOSE 1=INFO 2=WARNING 3=ERROR 4=FATAL）：

```bash
# Linux / macOS
export PADDLEONNXOCR_ORT_LOG_LEVEL=2

# Windows PowerShell
$env:PADDLEONNXOCR_ORT_LOG_LEVEL = "2"
```

PS: 具体参数请点到每一个方法内，有完整解释。

## API 服务

仓库自带基于 FastAPI 的 OCR 服务（模型长驻内存，CORS 全开），提供两个接口：

| 接口 | 方法 | 说明 |
|---|---|---|
| `/universalOcr` | POST | 通用 OCR（图片 / PDF 均可） |
| `/imageTableToHtml` | POST | 表格图片转 HTML |

请求体为 `{"content": ["图片URL或base64", ...]}`，返回 `{success, code, data, message}`。

### 本地启动

```bash
pip install fastapi uvicorn gunicorn   # api 服务额外依赖
python main.py                         # 默认 127.0.0.1:8000
```

### Docker 部署

提供了 Docker 构建启动脚本（自动构建镜像、启动容器并清理旧镜像），Windows 下请使用 WSL 子系统：

```bash
bash run.sh
```

容器对外映射端口 `80`，详见 `docker-compose.yaml`。

## 依赖项目

核心依赖（完整列表见 `pyproject.toml`）：

| 依赖 | 用途 |
|---|---|
| onnxruntime / openvino | 推理后端（二选一） |
| opencv-python-headless | 图像处理 |
| pillow | 图像输入支持 |
| shapely + pyclipper | 检测框后处理（多边形扩张） |
| modelscope | 模型自动下载 |
| pdfplumber + pymupdf | PDF 文字层 / 表格提取与扫描页渲染 |
| aiohttp / aiofiles / validators / filetype / deskew | 异步下载、输入校验、文件类型识别、去倾斜 |

## License

[MIT](LICENSE)
