# 合并模型评测指南 ## 概述 `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 ```