# RESTful API 参考

> FastAPI 服务的全部端点定义、请求/响应模型、功能初始化与运行时切换流程

- Repository: sml2h3/ddddocr
- GitHub: https://github.com/sml2h3/ddddocr
- Human wiki: https://grok-wiki.com/public/wiki/sml2h3-ddddocr-10e2eae686bf
- Complete Markdown: https://grok-wiki.com/public/wiki/sml2h3-ddddocr-10e2eae686bf/llms-full.txt

## Source Files

- `ddddocr/api/routes.py`
- `ddddocr/api/models.py`
- `ddddocr/api/server.py`
- `ddddocr/api/app.py`

---

<details>
<summary>相关源文件</summary>
以下文件用于生成此维基页面：
- [ddddocr/api/app.py](ddddocr/api/app.py)
- [ddddocr/api/routes.py](ddddocr/api/routes.py)
- [ddddocr/api/models.py](ddddocr/api/models.py)
- [ddddocr/api/server.py](ddddocr/api/server.py)
- [ddddocr/api/mcp.py](ddddocr/api/mcp.py)
</details>

# RESTful API 参考

DDDDOCR 项目提供两套互补的 FastAPI HTTP 服务：一套**独立应用**（`app.py`）面向单次请求即用的场景，自动按配置键缓存实例；一套**模块化服务**（`server.py` + `routes.py`）支持显式初始化、运行时模型切换、功能开关以及 MCP 协议集成。两者共享同一套 Pydantic 数据模型，均默认监听 `8000` 端口并开启全量 CORS。

---

## 架构概览

```text
┌─────────────────────────────────────────────────────┐
│                    FastAPI 应用层                     │
├──────────────┬──────────────────────────────────────┤
│  独立应用     │  模块化服务                            │
│  app.py       │  server.py → routes.py → mcp.py     │
├──────────────┴──────────────────────────────────────┤
│          公共数据模型  models.py                      │
├─────────────────────────────────────────────────────┤
│              ddddocr 核心引擎 (DdddOcr)              │
└─────────────────────────────────────────────────────┘
```

---

## 独立应用（app.py）

`app.py` 是一个可直接运行的 FastAPI 应用，通过环境变量控制默认参数，按配置键自动创建和缓存 OCR 实例，并在后台任务中清理闲置实例。

### 环境变量配置

| 环境变量 | 默认值 | 说明 |
|---|---|---|
| `DDDDOCR_OCR` | `true` | 是否启用 OCR |
| `DDDDOCR_DET` | `false` | 是否启用目标检测 |
| `DDDDOCR_OLD` | `false` | 是否使用旧版模型 |
| `DDDDOCR_BETA` | `false` | 是否使用 Beta 模型 |
| `DDDDOCR_USE_GPU` | `false` | 是否使用 GPU |
| `DDDDOCR_DEVICE_ID` | `0` | GPU 设备 ID |
| `DDDDOCR_SHOW_AD` | `true` | 是否显示广告 |
| `DDDDOCR_IMPORT_ONNX_PATH` | `""` | 自定义 ONNX 模型路径 |
| `DDDDOCR_CHARSETS_PATH` | `""` | 自定义字符集路径 |
| `DDDDOCR_HOST` | `127.0.0.1` | 监听地址 |
| `DDDDOCR_PORT` | `8000` | 监听端口 |
| `DDDDOCR_WORKERS` | `1` | 工作进程数 |

`Sources: [ddddocr/api/app.py:319-327]()`

### 端点一览

#### `GET /health`

健康检查端点，返回服务状态与时间戳。

**响应示例：**
```json
{"status": "ok", "timestamp": 1719100000.0}
```

`Sources: [ddddocr/api/app.py:330-332]()`

---

#### `POST /ocr`

接收 Base64 编码图片，执行 OCR 文字识别。通过 Query 参数控制模型配置，首次请求某配置时自动创建实例并缓存。

**Query 参数（均有环境变量默认值）：**

| 参数 | 类型 | 说明 |
|---|---|---|
| `ocr` | bool | 启用 OCR |
| `det` | bool | 启用目标检测 |
| `old` | bool | 使用旧版模型 |
| `beta` | bool | 使用 Beta 模型 |
| `use_gpu` | bool | 使用 GPU |
| `device_id` | int | GPU 设备 ID |
| `show_ad` | bool | 显示广告 |

**请求体（`OCRRequest`）：**

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `image` | string | ✅ | Base64 编码图片（最大 8 MB） |
| `probability` | bool | ❌ | 是否返回概率信息，默认 `false` |
| `colors` | List[str] | ❌ | 颜色过滤列表，如 `["red", "blue"]` |
| `custom_color_ranges` | Dict | ❌ | 自定义 HSV 颜色范围 |

**响应（`OCRResponse`）：**

| 字段 | 类型 | 说明 |
|---|---|---|
| `result` | str 或 Dict | 识别文本，或概率字典 |
| `probability` | Any | 概率信息（仅 `probability=true` 时） |
| `processing_time` | float | 处理耗时（秒） |

`Sources: [ddddocr/api/app.py:126-158](模型定义), [ddddocr/api/app.py:335-404](端点实现)`

---

#### `POST /ocr/file`

文件上传版 OCR 端点。接受 `multipart/form-data`，无需 Base64 编码。

**表单字段：**

| 字段 | 类型 | 说明 |
|---|---|---|
| `file` | UploadFile | 图片文件 |
| `probability` | bool/str | 是否返回概率 |
| `colors` | str (JSON) | 颜色列表 JSON 字符串 |
| `custom_color_ranges` | str (JSON) | 自定义颜色范围 JSON 字符串 |

Query 参数与 `/ocr` 相同。

`Sources: [ddddocr/api/app.py:408-495]()`

---

#### `POST /det`

目标检测端点，接收 Base64 编码图片，返回检测到的边界框列表。

**请求体（`Base64Image`）：**

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `image` | string | ✅ | Base64 编码图片 |

**响应（`DetectionResponse`）：**

| 字段 | 类型 | 说明 |
|---|---|---|
| `result` | List[List[int]] | 边界框坐标列表 `[[x1,y1,x2,y2], ...]` |
| `processing_time` | float | 处理耗时 |

`Sources: [ddddocr/api/app.py:500-539]()`

---

#### `POST /det/file`

文件上传版目标检测端点。

`Sources: [ddddocr/api/app.py:542-589]()`

---

#### `POST /slide_match`

滑块验证码匹配，接收目标图与背景图的 Base64 编码。

**请求体（`SlideMatchRequest`）：**

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `target_image` | string | ✅ | 滑块图片 Base64 |
| `background_image` | string | ✅ | 背景图片 Base64 |
| `simple_target` | bool | ❌ | 是否简化目标，默认 `false` |
| `flag` | bool | ❌ | 标记选项，默认 `false` |

**响应（`SlideMatchResponse`）：**

| 字段 | 类型 | 说明 |
|---|---|---|
| `result.target_x` | int | 滑块 X 偏移 |
| `result.target_y` | int | 滑块 Y 偏移 |
| `result.target` | List[int] | 目标位置坐标 |
| `processing_time` | float | 处理耗时 |

`Sources: [ddddocr/api/app.py:160-172](模型), [ddddocr/api/app.py:592-633](端点)`

---

#### `POST /slide_comparison`

滑块验证码图像差异比较，返回目标区域坐标。

**请求体（`SlideComparisonRequest`）：**

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `target_image` | string | ✅ | 带坑位图片 Base64 |
| `background_image` | string | ✅ | 完整背景图片 Base64 |

**响应（`SlideComparisonResponse`）：**

| 字段 | 类型 | 说明 |
|---|---|---|
| `result` | Dict[str, List[int]] | 差异区域坐标 |
| `processing_time` | float | 处理耗时 |

`Sources: [ddddocr/api/app.py:174-184](模型), [ddddocr/api/app.py:636-676](端点)`

---

#### `POST /set_charset_range`

设置当前 OCR 实例的字符识别范围。

**请求体（`CharsetRangeRequest`）：**

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `charset_range` | List[str] | ✅ | 字符范围列表，如 `["0-9", "a-z"]` |

**响应：**
```json
{
  "result": "字符范围设置成功",
  "charset_range": ["0-9", "a-z"],
  "processing_time": 0.001
}
```

`Sources: [ddddocr/api/app.py:186-198](模型), [ddddocr/api/app.py:680-718](端点)`

---

#### `GET /config`

获取当前默认配置、活跃实例数和运行环境信息。

`Sources: [ddddocr/api/app.py:721-740]()`

---

#### `GET /docs`、`GET /redoc`

自动生成的 Swagger UI 和 ReDoc API 文档。

---

## 模块化服务（server.py + routes.py）

模块化服务采用 `DDDDDOCRService` 类管理状态，通过 `/initialize` 端点显式初始化，支持运行时模型切换和功能开关。

### 服务生命周期

```text
客户端                   API 服务                     DDDDService
  │                        │                            │
  │  POST /initialize      │                            │
  │──────────────────────▶│  initialize(config)         │
  │                        │───────────────────────────▶│
  │                        │  创建 ocr/det/slide 实例    │
  │◀──────────────────────│  返回已加载模型列表          │
  │                        │                            │
  │  POST /switch-model    │                            │
  │──────────────────────▶│  switch_model(config)       │
  │                        │───────────────────────────▶│
  │                        │  替换指定模型实例            │
  │◀──────────────────────│                            │
  │                        │                            │
  │  POST /toggle-feature  │                            │
  │──────────────────────▶│  toggle_feature(config)     │
  │                        │───────────────────────────▶│
  │                        │  修改 enabled_features      │
  │◀──────────────────────│                            │
  │                        │                            │
  │  POST /ocr             │                            │
  │──────────────────────▶│  检查实例 + 功能开关        │
  │                        │  ocr_instance.classification│
  │◀──────────────────────│  返回识别结果               │
```

### 端点一览

#### `POST /initialize`

初始化服务，按需加载 OCR、目标检测和滑块模型。**每次调用会清除已有实例并重新创建**。

**请求体（`InitializeRequest`）：**

| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| `ocr` | bool | `true` | 启用 OCR 功能 |
| `det` | bool | `false` | 启用目标检测功能 |
| `old` | bool | `false` | 使用旧版 OCR 模型 |
| `beta` | bool | `false` | 使用 Beta 版 OCR 模型 |
| `use_gpu` | bool | `false` | 使用 GPU |
| `device_id` | int | `0` | GPU 设备 ID |
| `import_onnx_path` | str | `""` | 自定义 ONNX 模型路径 |
| `charsets_path` | str | `""` | 自定义字符集路径 |

**响应（`APIResponse`）：**
```json
{
  "success": true,
  "message": "服务初始化成功",
  "data": {
    "loaded_models": ["ocr", "slide"],
    "message": "服务初始化成功"
  }
}
```

`Sources: [ddddocr/api/models.py:10-19](模型), [ddddocr/api/server.py:33-80](服务逻辑)`

---

#### `POST /switch-model`

运行时切换模型配置，无需重新初始化整个服务。

**请求体（`SwitchModelRequest`）：**

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `model_type` | str | ✅ | 模型类型：`ocr`、`ocr_old`、`ocr_beta`、`det` |
| `use_gpu` | bool | ❌ | 使用 GPU，默认 `false` |
| `device_id` | int | ❌ | GPU 设备 ID，默认 `0` |

`Sources: [ddddocr/api/models.py:22-26](模型), [ddddocr/api/server.py:82-120](服务逻辑)`

---

#### `POST /toggle-feature`

动态开启或关闭特定功能。

**请求体（`ToggleFeatureRequest`）：**

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `feature` | str | ✅ | 功能名称：`ocr`、`detection`、`color_filter` |
| `enabled` | bool | ✅ | 是否启用 |

`Sources: [ddddocr/api/models.py:29-32](模型), [ddddocr/api/server.py:122-135](服务逻辑)`

---

#### `POST /ocr`

执行 OCR 识别。需先调用 `/initialize` 启用 OCR 功能。

**请求体（`OCRRequest`）：**

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `image` | string | ✅ | Base64 编码图片 |
| `png_fix` | bool | ❌ | 修复 PNG 透明背景问题 |
| `probability` | bool | ❌ | 返回概率信息 |
| `color_filter_colors` | List[str] | ❌ | 颜色过滤预设颜色列表 |
| `color_filter_custom_ranges` | List[List[List[int]]] | ❌ | 自定义 HSV 颜色范围 |
| `charset_range` | int 或 str | ❌ | 字符集范围限制 |

**响应（`APIResponse` 包装 `OCRResponse`）：**

| 字段 | 类型 | 说明 |
|---|---|---|
| `data.text` | str 或 null | 识别文本 |
| `data.probability` | Dict 或 null | 概率信息 |

`Sources: [ddddocr/api/models.py:35-42](模型), [ddddocr/api/routes.py:79-118](端点)`

---

#### `POST /detect`

执行目标检测。需先调用 `/initialize` 启用检测功能。

**请求体（`DetectionRequest`）：** 仅需 `image`（Base64）。

**响应：** `data.bboxes` 为 `List[List[int]]` 边界框列表。

`Sources: [ddddocr/api/models.py:45-47](模型), [ddddocr/api/routes.py:120-145](端点)`

---

#### `POST /slide-match`

滑块匹配。

**请求体（`SlideMatchRequest`）：**

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `target_image` | string | ✅ | 滑块图片 Base64 |
| `background_image` | string | ✅ | 背景图片 Base64 |
| `simple_target` | bool | ❌ | 是否为简单滑块 |

**响应（`SlideResponse`）：**

| 字段 | 类型 | 说明 |
|---|---|---|
| `target` | List[int] | 目标位置坐标 |
| `target_x` | int 或 null | X 偏移 |
| `target_y` | int 或 null | Y 偏移 |

`Sources: [ddddocr/api/models.py:50-54](模型), [ddddocr/api/routes.py:147-172](端点)`

---

#### `POST /slide-comparison`

滑块图像差异比较。

**请求体（`SlideComparisonRequest`）：** `target_image` + `background_image`，均为 Base64。

`Sources: [ddddocr/api/models.py:57-60](模型), [ddddocr/api/routes.py:174-197](端点)`

---

#### `GET /status`

获取当前服务状态。

**响应（`StatusResponse`）：**

| 字段 | 类型 | 说明 |
|---|---|---|
| `service_status` | str | 服务状态，固定 `"running"` |
| `loaded_models` | List[str] | 已加载模型列表 |
| `enabled_features` | List[str] | 已启用功能列表 |
| `version` | str | 版本号 |
| `uptime` | float | 运行时长（秒） |

`Sources: [ddddocr/api/models.py:70-76](模型), [ddddocr/api/server.py:137-153](服务逻辑)`

---

#### `GET /health`

健康检查，返回 `{"status": "healthy", "timestamp": ...}`。

`Sources: [ddddocr/api/routes.py:204-207]()`

---

#### `GET /`

根路径，返回 HTML 页面，包含 Swagger UI、ReDoc 和服务状态的链接。

`Sources: [ddddocr/api/routes.py:20-50]()`

---

## MCP 协议端点

模块化服务通过 `/mcp` 前缀暴露 MCP（Model Context Protocol）接口，供 AI Agent 调用。

```text
GET  /mcp/capabilities   → 声明可用工具及其参数 Schema
POST /mcp/call           → 调用指定工具
GET  /mcp/               → 协议信息与端点索引
```

### 可用 MCP 工具

| 工具名 | 功能 | 必填参数 |
|---|---|---|
| `ddddocr_initialize` | 初始化服务 | 无（均可选） |
| `ddddocr_ocr` | OCR 识别 | `image` |
| `ddddocr_detection` | 目标检测 | `image` |
| `ddddocr_slide_match` | 滑块匹配 | `target_image`, `background_image` |
| `ddddocr_slide_comparison` | 滑块比较 | `target_image`, `background_image` |
| `ddddocr_status` | 服务状态 | 无 |

### MCP 请求/响应模型

**请求（`MCPRequest`）：**

```json
{
  "method": "ddddocr_ocr",
  "params": {"image": "<base64>", "probability": true},
  "id": "req-001"
}
```

**成功响应（`MCPResponse`）：**

```json
{
  "result": {"text": "abc123"},
  "error": null,
  "id": "req-001"
}
```

**错误响应：**

```json
{
  "result": null,
  "error": {"code": -1, "message": "OCR功能未初始化", "data": null},
  "id": "req-001"
}
```

`Sources: [ddddocr/api/mcp.py:1-228]()`

---

## 通用响应模型

所有模块化服务端点（除 `/status` 和 `/health`）使用统一的 `APIResponse` 包装：

```json
{
  "success": true,
  "message": "操作成功",
  "data": { ... }
}
```

独立应用端点（`app.py`）直接返回业务数据，不使用统一包装。

`Sources: [ddddocr/api/models.py:63-67]()`

---

## 实例管理策略

两套服务采用不同的实例管理策略：

| 维度 | 独立应用（app.py） | 模块化服务（server.py） |
|---|---|---|
| 初始化时机 | 首次请求时自动创建 | 显式调用 `/initialize` |
| 缓存键 | 配置参数组合字符串 | 无缓存，直接替换 |
| 清理策略 | 后台任务清理闲置 >1h 的实例 | 无自动清理 |
| 模型切换 | 请求不同的 Query 参数 | 调用 `/switch-model` |
| 功能开关 | 通过 Query 参数即时切换 | 调用 `/toggle-feature` 影响后续请求 |

独立应用的实例缓存键格式为 `ocr={ocr}-det={det}-old={old}-beta={beta}-gpu={use_gpu}-dev={device_id}`，每种配置组合对应一个独立实例。

`Sources: [ddddocr/api/app.py:239-281](实例管理), [ddddocr/api/server.py:22-153](服务类)`

---

## 启动方式

**独立应用：**

```bash
# 直接运行
python -m ddddocr.api.app

# 环境变量配置
DDDDOCR_HOST=0.0.0.0 DDDDOCR_PORT=8080 python -m ddddocr.api.app
```

**模块化服务：**

```python
from ddddocr.api.server import run_server
run_server(host="0.0.0.0", port=8000)
```

`Sources: [ddddocr/api/app.py:743-751](独立启动), [ddddocr/api/server.py:200-206](模块化启动)`

---

## 错误处理

所有端点均返回标准 HTTP 错误码：

| 状态码 | 含义 | 典型场景 |
|---|---|---|
| 400 | 请求参数错误 | Base64 解码失败、图片为空、功能未初始化 |
| 500 | 服务器内部错误 | 模型加载失败、识别异常 |

模块化服务还配有全局异常处理器，未捕获的异常统一返回 500 并附带错误详情（调试模式下包含完整堆栈）。

`Sources: [ddddocr/api/routes.py:209-219](全局异常处理)`
