304 lines
9.0 KiB
Markdown
Executable File
304 lines
9.0 KiB
Markdown
Executable File
# 合并模型评测指南
|
||
|
||
## 概述
|
||
|
||
`val_merged_model.py` 是专门用于评测合并双ROI模型的脚本。它基于 `val.py` 的评测逻辑,但针对双ROI模型进行了适配。
|
||
|
||
## 功能特性
|
||
|
||
1. **双ROI数据加载**:为ROI0和ROI1分别创建数据加载器
|
||
2. **同步推理**:同时对两个ROI进行推理
|
||
3. **跨ROI结果融合**:使用NmsForScale算法合并两个ROI的检测结果,避免重复检测
|
||
4. **完整指标计算**:计算2D mAP和3D指标(深度误差、方向误差、中心点误差)
|
||
|
||
## 工作流程
|
||
|
||
```
|
||
输入数据
|
||
↓
|
||
ROI0 Dataloader → 推理 → NMS → ↘
|
||
跨ROI融合 → 2D/3D指标计算
|
||
ROI1 Dataloader → 推理 → NMS → ↗
|
||
```
|
||
|
||
### 详细步骤
|
||
|
||
1. **加载合并模型**:加载包含 `model_roi0` 和 `model_roi1` 的合并模型
|
||
2. **创建数据加载器**:
|
||
- ROI0: 裁剪区域 [0, 120, 1920, 1080]
|
||
- ROI1: 中心区域 [704, 352],原始图像 [1920, 1080]
|
||
3. **推理**:对两个ROI同时进行前向传播
|
||
4. **NMS**:对每个ROI的检测结果独立进行NMS
|
||
5. **跨ROI融合**:使用NmsForScale算法合并检测结果:
|
||
- 移除边缘伪影(IoU > 0.9且超出ROI边界)
|
||
- 抑制重复检测(IoU > 0.3,保留更靠近ROI中心的检测)
|
||
- 移除高度包含的检测(IoU_in > 0.8)
|
||
6. **指标计算**:对融合后的结果计算评测指标
|
||
|
||
## 使用方法
|
||
|
||
### 基本用法
|
||
|
||
```bash
|
||
python eval_tools/val_merged_model.py \
|
||
--data data/mono3d.yaml \
|
||
--weights release/yolov5s-30w/merged_model.pt \
|
||
--imgsz 704 352 \
|
||
--batch-size 1
|
||
```
|
||
|
||
### 参数说明
|
||
|
||
| 参数 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `--data` | `data/mono3d.yaml` | 数据集配置文件路径 |
|
||
| `--weights` | 必需 | 合并模型权重文件路径(.pt格式)|
|
||
| `--batch-size` | `1` | 批大小(仅支持1)|
|
||
| `--imgsz` | `[704, 352]` | 推理图像尺寸 [宽度, 高度] |
|
||
| `--conf-thres` | `0.001` | NMS置信度阈值(低值用于AP计算)|
|
||
| `--conf-thres-plot` | `0.25` | 可视化和3D指标的置信度阈值 |
|
||
| `--iou-thres` | `0.6` | NMS的IoU阈值 |
|
||
| `--max-det` | `300` | 每张图片最大检测数 |
|
||
| `--device` | `''` | 设备(如'0'或'cpu')|
|
||
| `--workers` | `8` | 数据加载器工作线程数 |
|
||
| `--project` | `runs/val_merged` | 结果保存目录 |
|
||
| `--name` | `exp` | 实验名称 |
|
||
| `--verbose` | - | 按类别报告mAP |
|
||
| `--half` | - | 使用FP16半精度推理 |
|
||
|
||
### 完整示例
|
||
|
||
```bash
|
||
# 基本评测
|
||
python eval_tools/val_merged_model.py \
|
||
--data data/mono3d.yaml \
|
||
--weights release/yolov5s-30w/merged_model.pt \
|
||
--imgsz 704 352
|
||
|
||
# 使用GPU加速和半精度
|
||
python eval_tools/val_merged_model.py \
|
||
--data data/mono3d.yaml \
|
||
--weights release/yolov5s-30w/merged_model.pt \
|
||
--imgsz 704 352 \
|
||
--device 0 \
|
||
--half
|
||
|
||
# 详细输出(按类别显示mAP)
|
||
python eval_tools/val_merged_model.py \
|
||
--data data/mono3d.yaml \
|
||
--weights release/yolov5s-30w/merged_model.pt \
|
||
--imgsz 704 352 \
|
||
--verbose
|
||
|
||
# 自定义输出目录
|
||
python eval_tools/val_merged_model.py \
|
||
--data data/mono3d.yaml \
|
||
--weights release/yolov5s-30w/merged_model.pt \
|
||
--imgsz 704 352 \
|
||
--project runs/my_eval \
|
||
--name merged_exp1
|
||
```
|
||
|
||
## 输出结果
|
||
|
||
### 控制台输出
|
||
|
||
评测过程中会实时显示:
|
||
|
||
```
|
||
Class Images Instances P R mAP50 mAP50-95 Matched Depth(m) Orient(°) Center(m)
|
||
all 50 150 0.856 0.823 0.891 0.672 89 2.345 12.678 0.234
|
||
```
|
||
|
||
- **Class**: 类别名称
|
||
- **Images**: 处理的图片数量
|
||
- **Instances**: 真实标注数量
|
||
- **P**: 精确率
|
||
- **R**: 召回率
|
||
- **mAP50**: mAP@0.5
|
||
- **mAP50-95**: mAP@0.5:0.95
|
||
- **Matched**: 3D匹配的检测数
|
||
- **Depth(m)**: 平均深度误差(米)
|
||
- **Orient(°)**: 平均方向误差(度)
|
||
- **Center(m)**: 平均中心点误差(米)
|
||
|
||
### 最终统计
|
||
|
||
```
|
||
3D Metrics (Fused ROI0+ROI1):
|
||
Total matched: 89
|
||
Depth error (abs): 2.345m
|
||
Orientation error: 12.678°
|
||
Center error: 0.234m
|
||
```
|
||
|
||
### 保存的文件
|
||
|
||
结果保存在 `--project/--name` 目录下:
|
||
|
||
- `confusion_matrix.png`: 混淆矩阵图
|
||
- `F1_curve.png`: F1曲线
|
||
- `P_curve.png`: 精确率曲线
|
||
- `R_curve.png`: 召回率曲线
|
||
- `PR_curve.png`: PR曲线
|
||
|
||
## ROI配置
|
||
|
||
脚本内置了ROI配置,与 `test_val_merged_model.py` 保持一致:
|
||
|
||
```python
|
||
# ROI0: 裁剪区域
|
||
roi0 = (0, 120, 1920, 1080)
|
||
ori_img_size_roi0 = None
|
||
|
||
# ROI1: 中心区域
|
||
roi1 = (704, 352)
|
||
ori_img_size_roi1 = (1920, 1080)
|
||
|
||
# 跨ROI NMS使用的ROI坐标(原始图像坐标系)
|
||
roi_list = [
|
||
(0, 120, 1920, 1080), # ROI0
|
||
(608, 364, 1312, 716) # ROI1在原始图像中的坐标
|
||
]
|
||
```
|
||
|
||
## 跨ROI NMS算法
|
||
|
||
`NmsForScale` 函数实现了跨ROI的检测融合:
|
||
|
||
1. **边缘伪影过滤**:
|
||
- 计算检测框与ROI的IoU
|
||
- 如果IoU > 0.9且检测框超出ROI边界,则移除
|
||
|
||
2. **重复检测抑制**:
|
||
- 对于来自不同ROI的检测框
|
||
- 如果IoU > 0.3(高度重叠)
|
||
- 保留距离ROI中心更近的检测
|
||
|
||
3. **包含关系处理**:
|
||
- 如果一个检测框被另一个检测框高度包含(IoU_in > 0.8)
|
||
- 移除被包含的检测框
|
||
|
||
## 注意事项
|
||
|
||
1. **批大小限制**:合并模型评测仅支持 `batch_size=1`
|
||
2. **模型格式**:仅支持PyTorch .pt格式的合并模型(包含Model_Merged类)
|
||
3. **数据集要求**:数据集必须包含3D标注(48列标签格式)
|
||
4. **内存使用**:同时加载两个ROI的数据会增加内存使用
|
||
5. **速度**:由于需要推理两个ROI和跨ROI融合,速度会比单ROI评测慢
|
||
|
||
## 与单ROI评测的对比
|
||
|
||
| 特性 | val.py (单ROI) | val_merged_model.py (双ROI) |
|
||
|------|----------------|------------------------------|
|
||
| 批大小 | 支持任意 | 仅支持1 |
|
||
| 数据加载器 | 单个 | 两个(ROI0+ROI1)|
|
||
| 推理次数 | 1次/图像 | 2次/图像 |
|
||
| NMS | 单次 | 2次独立+跨ROI融合 |
|
||
| 结果 | 单ROI检测 | 融合后的全图检测 |
|
||
| 速度 | 快 | 较慢(约2倍推理时间)|
|
||
| 覆盖范围 | 单个ROI | 全图覆盖 |
|
||
|
||
## 故障排除
|
||
|
||
### 问题1:模型加载失败
|
||
|
||
```
|
||
ValueError: Model at xxx is not a merged dual-ROI model
|
||
```
|
||
|
||
**解决方法**:确保模型是通过 `merge_models_of_2roi.py` 创建的合并模型,包含 `model_roi0` 和 `model_roi1` 属性。
|
||
|
||
### 问题2:数据加载器长度不匹配
|
||
|
||
```
|
||
WARNING Dataloader lengths mismatch: ROI0=100, ROI1=98
|
||
```
|
||
|
||
**解决方法**:检查数据集配置,确保两个ROI访问相同的图像文件。
|
||
|
||
### 问题3:路径不匹配
|
||
|
||
```
|
||
WARNING Path mismatch: xxx vs yyy
|
||
```
|
||
|
||
**解决方法**:这通常表示两个数据加载器返回的图像顺序不一致,检查数据集配置和路径。
|
||
|
||
### 问题4:内存不足
|
||
|
||
**解决方法**:
|
||
- 减少 `--workers` 数量
|
||
- 使用 `--half` 启用FP16推理
|
||
- 在CPU上运行:`--device cpu`
|
||
|
||
## 相关文件
|
||
|
||
- `val.py`: 单ROI模型评测脚本
|
||
- `merge_models_of_2roi.py`: 合并两个ROI模型的脚本
|
||
- `test_val_merged_model.py`: 合并模型推理测试脚本(仅推理,不计算指标)
|
||
- `val_merged_model.py`: 本脚本,合并模型完整评测
|
||
|
||
## 工作流程示例
|
||
|
||
完整的训练+合并+评测流程:
|
||
|
||
```bash
|
||
# 1. 训练ROI0模型
|
||
python train_mono3d.py --data data/mono3d.yaml --roi 0 120 1920 1080 --weights yolov5s.pt
|
||
|
||
# 2. 训练ROI1模型
|
||
python train_mono3d.py --data data/mono3d.yaml --roi 704 352 --ori-img-size 1920 1080 --weights yolov5s.pt
|
||
|
||
# 3. 评测单个模型(可选)
|
||
python val.py --weights runs/train/roi0_exp/weights/last.pt --data data/mono3d.yaml --roi 0 120 1920 1080
|
||
python val.py --weights runs/train/roi1_exp/weights/last.pt --data data/mono3d.yaml --roi 704 352 --ori-img-size 1920 1080
|
||
|
||
# 4. 合并模型
|
||
python eval_tools/merge_models_of_2roi.py \
|
||
--roi0_model_path runs/train/roi0_exp/weights/last.pt \
|
||
--roi1_model_path runs/train/roi1_exp/weights/last.pt \
|
||
--save_dir release/merged \
|
||
--skip-export # 仅保存合并模型,不导出ONNX
|
||
|
||
# 5. 评测合并模型
|
||
python eval_tools/val_merged_model.py \
|
||
--data data/mono3d.yaml \
|
||
--weights release/merged/merged_model.pt \
|
||
--imgsz 704 352
|
||
|
||
# 6. 推理测试(可选)
|
||
python eval_tools/test_val_merged_model.py \
|
||
--source /path/to/test/images \
|
||
--weights release/merged/merged_model.pt \
|
||
--model-type torchscript
|
||
```
|
||
|
||
## 扩展说明
|
||
|
||
如果需要修改ROI配置,编辑脚本中的以下部分:
|
||
|
||
```python
|
||
# 在 run() 函数中,约第375行
|
||
roi0 = (0, 120, 1920, 1080) # 修改ROI0坐标
|
||
roi1 = (704, 352) # 修改ROI1尺寸
|
||
ori_img_size_roi1 = (1920, 1080) # 修改原始图像尺寸
|
||
|
||
# 在跨ROI NMS部分,约第431行
|
||
roi_list = [
|
||
(0, 120, 1920, 1080), # ROI0坐标
|
||
(608, 364, 1312, 716) # ROI1在原始图像中的坐标(需要计算)
|
||
]
|
||
```
|
||
|
||
计算ROI1在原始图像中的坐标:
|
||
```python
|
||
# 如果ROI1是中心裁剪,计算方式:
|
||
ori_w, ori_h = 1920, 1080
|
||
roi1_w, roi1_h = 704, 352
|
||
x1 = (ori_w - roi1_w) // 2 # 608
|
||
y1 = (ori_h - roi1_h) // 2 # 364
|
||
x2 = x1 + roi1_w # 1312
|
||
y2 = y1 + roi1_h # 716
|
||
```
|