Files
nanocode/urinecheck/docs/python-json-implementation-plan.md
Ubuntu 32b43f85bd a
2026-07-03 16:58:28 +08:00

128 lines
4.2 KiB
Markdown
Raw Permalink 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.
# Python后端 JSON数据尿检识别 - 技术实施方案
> 基于 C++ `ProcessJsonDataRequest` 逐行翻译到 Python
> 依赖:`/usr/local/Models/ml.json` + `*.data` (OpenCV RTrees 模型)
---
## 1. 可行性验证
| 检查项 | 状态 |
|--------|------|
| OpenCV 版本 | 4.13.0 ✅ |
| cv2.ml.RTrees_load() 加载 .data 文件 | ✅ uro_0, glu_1, glu-rts-M1 均加载成功 |
| RTrees.predict() 预测 | ✅ `predict(sample)` 返回浮点数 |
| /usr/local/Models/ 所有模型文件存在 | ✅ 14项×2+ (Green+Rts) 全部存在 |
| ml.json 配置完整 | ✅ 包含所有14项×21种试纸类型配置 |
---
## 2. 总体架构
```
POST /api/urinecheck/analyze-json
│
├── 接收 JSON body (与txt文件格式一致)
│
├── MLConfigLoader ─── 解析 /usr/local/Models/ml.json
│ ├── 构建 model_lookup[paperType][position] = (model, indexFunc, indexMap)
│ └── 标注 PRO/MAU/SG/pH 的 position
│
├── UrineJsonRecognizer
│ ├── 1. 解析输入JSON
│ ├── 2. extract paperType from extend
│ ├── 3. 逐帧处理
│ │ └── 每帧: mapData[id→[6 floats]] → ML推理 → {position: rawIndex}
│ ├── 4. CountResultsModal (多帧投票)
│ ├── 5. PRO/MAU + SG/PH 关联修正
│ ├── 6. indexMap 映射
│ └── 7. 构建输出JSON
│
└── 返回 {"score":"100", "status":"0", "data": [{id, index}, ...]}
```
---
## 3. 实施步骤
### Step 1: 新建 `ml_config.py` — ML配置加载器
**功能**:解析 `/usr/local/Models/ml.json`,构建运行时查表结构
```python
class MLConfigLoader:
def load(self):
# 解析 ml.json
# 对每个 item (uro/glu/ket/...):
# 对每个 model entry (positon, id, filepath, algorithm, indexmap):
# paperType = j (model数组中的索引)
# if positon >= 0:
# models[paperType][positon] = RTrees.load(filepath)
# result_funcs[paperType][positon] = indexFuncName
# stat_ids[paperType][positon] = id
# index_maps[paperType][positon] = [int(x) for x in indexmap.split(',')]
# if name == 'pro': positionsPro[paperType] = positon
# ... etc
```
### Step 2: 新建 `json_recognizer.py` — JSON数据识别器
**核心类**:`UrineJsonRecognizer`
```python
class UrineJsonRecognizer:
def recognize(self, json_data: dict) -> dict:
# 完整复制 ProcessJsonDataRequest 逻辑
...
def _get14_results(self, map_data: dict, paper_type: int) -> dict:
# 完整复制 UrineCheck14::Get14Results(mapData, X) 逻辑
...
```
**各检测项的结果索引修正函数**(直接翻译C++):
- `_red_pro_index(p, h)` — if ret>0 and (h<25 or h>110) → 0
- `_red_mau_index(p, h)` — if ret>0 and (h<30 or h>115) → 0
- `_red_ket_index(p, h)` — if ret>1 and 45<h<145 → 0
- `_red_nit_index(p, h)` — if ret>0 and 40<h<140 → 0
- `_red_uro_index(p, h)` — if ret>0 and 25<h<150 → 0
- 其余直接 `round(p)`
### Step 3: 添加 API 路由
在 `routers/urinecheck.py` 中添加:
```python
@router.post("/analyze-json")
async def analyze_json(request: JsonDataRequest, ...):
recognizer = get_recognizer() # 全局单例
return recognizer.recognize(request.model_dump())
```
### Step 4: 在 `schemas.py` 中添加请求模型
### Step 5: 在 `app.py` 中初始化识别器(startup event)
---
## 4. 关键差异注意事项
| C++ | Python |
|-----|--------|
| Json::Value | dict/list |
| map<int, Ptr<RTrees>> | dict[int, cv2.ml.RTrees] |
| `atoi()` string→int | `int()` 或 `float()` |
| `split(s, ',', vs)` | `s.split(',')` |
| `GetModal1()` → 众数 | `collections.Counter.most_common(1)` |
| `GetPredictResultVal(data)` | `model.predict(np.array([data], dtype=np.float32))` |
---
## 5. 文件清单
| 文件 | 操作 | 功能 |
|------|------|------|
| `backend/ml_config.py` | **新建** | ML配置加载器 |
| `backend/json_recognizer.py` | **新建** | JSON数据识别核心逻辑 |
| `backend/schemas.py` | **修改** | 添加 JsonDataRequest |
| `backend/routers/urinecheck.py` | **修改** | 添加 /analyze-json 路由 |
| `backend/app.py` | **修改** | 启动时初始化识别器 |