# 鞋子检测模型训练指南

## 当前主方案：YOLOv8s-640 + 脚部 ROI 训练

当前项目的主训练方向已经调整为：
- 只训练 `yolov8s`、输入尺寸固定 `640x640`
- 训练数据不再直接使用“整张场景图”或“鞋子纯特写图”
- 优先根据真实`人体框`裁出更接近线上输入分布的“脚部 ROI 图”，再训练鞋检测模型

这样做的原因是线上链路并不是直接在整张图上找鞋，而是：
1. 先从人体框生成脚部 ROI
2. 再在脚部 ROI 上做鞋检测

因此训练阶段也尽量模拟这个输入分布，保留一些裤脚、地面和周围背景，避免训练样本过于像商品特写。

### ROI 规则

优先原则：
- 最优方式：如果有`人体框`，直接按线上人体下部 ROI 规则裁图
- 次优方式：如果只有`鞋框`，再按鞋框扩图，尽量模拟人体下部脚部 ROI 的视觉分布

线上人体下部 ROI 规则：
- 已知人体框 `(x, y, w, h)`
- `roi_x = x - 0.24w`
- `roi_y = y + 0.64h`
- `roi_w = 1.48w`
- `roi_h = 0.58h`

这条规则的目标是：
- 横向比人体略宽，尽量把双脚都包进去
- 纵向覆盖人体下部到脚下地面
- 让鞋模型看到的输入更接近真实线上两阶段链路

当前推荐的数据准备方式：

1. PPE 数据保留 `Person + shoe`

```bash
python 05_prepare_ppe_shoe_subset.py --mode roi-source
```

输出目录：
- `datasets/ppe-person-shoes`

2. Open Images 重新下载，并保留 `Person + shoe`

```bash
python 01_download_dataset.py --source openimages --mode roi-source --max-samples 100000
```

默认输出目录：
- `datasets/openimages-person-shoes-yolo`

3. 构建 ROI 化训练集

```bash
python 09_build_roi_shoe_dataset.py --clean
```

构建规则：
- 如果源数据里有真实 `Person` 框，直接按人体下部 ROI 规则裁图
- 只有在没有人框时，才退回鞋框扩图 fallback

如果只有鞋框，没有人体框：
- 仍然可以做鞋框 fallback 扩图
- 但目标不是做鞋子纯特写，而是尽量近似“人体下部脚部 ROI”
- 也就是保留一定裤脚、脚下地面和周围背景
- 裁图会自动截到图像边界内

训练目标总结：
- 不要做鞋子纯特写
- 要做“脚部局部图”
- 让训练输入尽量贴近线上“人体下部脚部 ROI”

### 新主流程

1. 准备 ROI 源数据集

```bash
python 05_prepare_ppe_shoe_subset.py --mode roi-source
python 01_download_dataset.py --source openimages --mode roi-source --max-samples 100000
```

2. 构建 ROI 化训练集

```bash
python 09_build_roi_shoe_dataset.py --clean
```

输出目录：
- `datasets/shoe-roi-mix`

3. 训练新的 ROI 模型

```bash
12_train_roi_yolov8s_640.bat
```

模型输出目录：
- `runs/roi_yolov8s_640`

说明：
- 新模型会写到新的项目目录，不覆盖之前已有模型
- 如果 `train_roi` 已存在，Ultralytics 会自动递增运行目录名

## 当前实验结论

截至目前，项目内已经验证了几条比较明确的结论：

- 只看公开验证集 `mAP` 不够，必须同时看真实 `roi-shoes` 业务图的框位置和召回情况
- 训练输入做成“人体下部脚部 ROI”是正确方向，整体上明显优于早期“鞋子单类紧框”训练
- 扩大 Open Images 源图数量是有价值的，但必须配合 ROI 质量过滤，否则数据越多，噪声也越多
- `100k filtered` 这一条线已经比 `20k filtered` 更有潜力，尤其对“大 ROI、细节丰富鞋面”的适应性更好

当前几版模型的经验判断是：

- 旧主力模型：对“小目标、模糊目标、简单轮廓”更稳
- `100k filtered` 系列：对“大一点、细节更丰富、纹理更复杂”的鞋更好
- 在 `100k filtered` 的已跑版本里，`100 epochs` 是当前最均衡、最值得继续迭代的一版

## 后续训练方向

后续训练主线建议固定为：

1. 以 `100k filtered` 训练集为基础继续迭代
2. 以 `100 epochs` 版本权重作为下一轮微调底座
3. 补充一批真实线上风格的脚部 ROI 标注图，做小规模业务微调
4. 最终以真实 ROI 评测结果为主，而不是只看公开验证集 `mAP`

推荐优先补充的真实 ROI 图类型：

- 小而模糊、边缘不清、低对比度的鞋
- 大 ROI、鞋面细节丰富、纹理复杂的鞋
- 单鞋与双鞋混合出现、地面背景复杂的脚部 ROI

建议的后续流程：

```bash
# 1. 继续维护 100k filtered 公开 ROI 数据底座
python 05_prepare_ppe_shoe_subset.py --mode roi-source
python 01_download_dataset.py --source openimages --mode roi-source --max-samples 100000
python 09_build_roi_shoe_dataset.py --clean

# 2. 使用 100k filtered 数据训练基础 ROI 模型
12_train_roi_yolov8s_640.bat

# 3. 在补充真实 ROI 标注后，再做业务微调
# 建议直接从 100k-100 这一版权重继续训练
```

当前项目建议保留两套判断标准：

- 公开验证集指标：
  - 观察 `precision / recall / mAP50 / mAP50-95`
- 真实业务 ROI 效果：
  - 看是否漏检
  - 看检测框是否真正落在鞋区域
  - 看不同目标类型下的稳定性，而不是只看总平均数

## 方案：640x640 单模型（部署时用2窗口）

**训练阶段**：
- 输入：640x640 完整图片
- 模型：YOLOv8s
- 输出：640x640 模型文件

**部署阶段**（pipeline配置）：
- 原图 1920x1080
- 分成 2 个 960x1080 窗口
- 每个窗口 resize 到 640x640 送入模型
- 合并检测结果

---

## 目录结构

```
train/
├── README.md                 # 本文件
├── 01_download_dataset.py    # 下载鞋子数据集（推荐 Open Images）
├── 02_train.bat              # Windows 一键训练脚本
├── 03_export_onnx.bat        # 导出 ONNX 脚本
├── 04_convert_rknn.py        # 转换为 RKNN 脚本
├── 05_prepare_ppe_shoe_subset.py # 提取 PPE 鞋子单类子集
├── 06_finetune_ppe.bat       # 用 PPE 鞋子子集做二阶段微调
├── data.yaml.template        # 数据集配置文件
└── samples/                  # 示例图片
    ├── calibration/          
    ├── test_images/          
    └── README.md
```

---

## 快速开始

### 1. 下载数据集

```bash
cd train
python 01_download_dataset.py --source openimages --max-samples 5000
```

### 2. 准备配置

```bash
脚本会自动生成 datasets/openimages-shoes-yolo/data.yaml
```

### 3. 训练（640x640）

```bash
02_train.bat
```

或手动：
```bash
yolo detect train \
    data=datasets/openimages-shoes-yolo/data.yaml \
    model=yolov8s.pt \
    epochs=150 \
    imgsz=640 \
    batch=16 \
    device=0
```

**训练参数**：
- 模型：YOLOv8s（速度和精度平衡）
- 输入：640x640
- 预计时间：30-60分钟

### 4. 导出 ONNX

```bash
03_export_onnx.bat
```

### 5. 转换为 RKNN

在 Ubuntu PC 上：
```bash
python 04_convert_rknn.py runs/detect/train/weights/best.onnx -o shoe_detector_640.rknn -t rk3588
```

### 6. 部署（2窗口配置）

复制到 RK3588：
```bash
scp shoe_detector_640.rknn orangepi@<rk3588_ip>:/home/orangepi/apps/OrangePi3588Media/models/
```

Pipeline 配置（部署阶段用2窗口）：
```json
{
  "id": "pre_shoe",
  "type": "preprocess",
  "windows": [
    {"x": 0, "y": 0, "w": 960, "h": 1080},
    {"x": 960, "y": 0, "w": 960, "h": 1080}
  ],
  "dst_w": 640,
  "dst_h": 640
}
```

### 7. 方案 A：PPE 二阶段微调

当 Open Images 基础模型训练完成后，可继续用 PPE 鞋子子集做场景微调：

```bash
python 05_prepare_ppe_shoe_subset.py
06_finetune_ppe.bat
```

PPE 鞋子子集来源：
- `boots`
- `no_boots`

这两个类会统一映射成单类：
- `shoe`

---

## 类别说明（Open Images）

Open Images 官方鞋类层级中，`Footwear` 的子类包括：
- `Boot`
- `Sandal`
- `High heels`
- `Roller skates`

本项目推荐下载：
- `Footwear`
- `Boot`

可选补充：
- `Sandal`

不建议默认加入：
- `High heels`
- `Roller skates`

训练时统一映射为单一类别：
- `0: shoe`

这样模型目标更聚焦，先尽量把鞋子稳定检出，再在后处理里判断是否为黑色鞋。

---

## 相关链接

- [Open Images 数据集](https://storage.googleapis.com/openimages/web/index.html)
- [Ultralytics YOLOv8](https://docs.ultralytics.com/)
