Files
yolov26_3d/eval_tools/docs/EVAL_FRAMEWORK_GUIDE.md
2026-06-24 09:35:46 +08:00

23 KiB
Executable File
Raw Permalink Blame History

模型评测框架使用指南

入口脚本:eval_tools/core/run_eval_with_config.sh


目录

  1. 框架概览
  2. 目录结构
  3. 核心流程
  4. 配置文件说明
  5. 命令行参数说明
  6. 数据格式
  7. 评测指标
  8. ROI GT 处理
  9. 模型对比(共同匹配集)
  10. Heading 误差分析
  11. 输出结果
  12. 使用示例
  13. 常见问题

1. 框架概览

本框架用于评测 YOLOv5-3D 模型的 2D 检测与 3D 定位性能,支持:

  • 2D 检测评测:全部 14 个类别的 Precision / Recall / AP / mAP
  • 3D 检测评测vehicle / pedestrian / bicycle / rider 的横向误差、纵向误差、heading 误差
  • ROI GT 过滤:评测坐标系与训练时保持一致
  • 距离区间分析按纵向距离z轴和横向距离x轴分段统计 3D 指标
  • 多模型对比基于共同匹配集Common Matches公平比较两个模型的 3D 性能
  • Heading 误差分析:提取、可视化、分析方向预测误差

架构图

eval_tools/core/run_eval_with_config.sh
            │
            ▼
eval_tools/core/eval.py            ← 主入口 Python 脚本
            │
            ├─── eval_tools/configs/*.yaml   ← 配置文件
            │
            └─── eval_tools/evaluator/       ← 核心评测引擎
                      ├── evaluator.py       ← 主控流程、并行调度
                      ├── parser.py          ← GT / 检测结果解析
                      ├── matcher.py         ← 2D IoU 匹配
                      ├── metrics_2d.py      ← 2D 指标计算
                      ├── metrics_3d.py      ← 3D 指标计算
                      └── roi_processor.py   ← ROI 坐标系对齐

2. 目录结构

eval_tools/
├── core/
│   ├── eval.py                         # 主评测脚本
│   ├── run_eval_with_config.sh         # 单模型评测入口(当前默认入口)
│   ├── run_eval.sh                     # 早期版本入口(无配置文件)
│   ├── run_eval_2d_only.sh             # 仅 2D 评测
│   ├── run_eval_3d_only.sh             # 仅 3D 评测
│   └── run_evaluation_example.sh       # 示例脚本
│
├── configs/
│   ├── eval_config_mono3d-roi0.yaml        # mono3d 模型 ROI0 配置
│   ├── eval_config_mono3d-roi1.yaml        # mono3d 模型 ROI1 配置
│   ├── eval_config_yolov5s-roi0.yaml       # yolov5s 模型 ROI0 配置
│   ├── eval_config_yolov5s-roi1.yaml       # yolov5s 模型 ROI1 配置
│   ├── eval_config_yolov5s_cncap-roi0.yaml # yolov5s CNCAP 测试集 ROI0当前默认
│   └── eval_config_yolov5s_cncap-roi1.yaml # yolov5s CNCAP 测试集 ROI1
│
├── evaluator/
│   ├── __init__.py
│   ├── evaluator.py       # 主评测器(数据加载、调度、报告生成)
│   ├── parser.py          # 真值 / 检测结果解析器
│   ├── matcher.py         # 2D IoU 匹配器
│   ├── metrics_2d.py      # 2D 指标计算P/R/AP/mAP
│   ├── metrics_3d.py      # 3D 指标计算Lat/Long/Heading
│   └── roi_processor.py   # ROI GT 处理器
│
├── model_comparison/
│   ├── find_common_matches.py           # 找出两模型共同匹配的 GT
│   ├── compare_models.py                # 生成双模型对比报告
│   ├── compare_models_with_common_matches.sh  # 一键双模型对比脚本
│   ├── generate_eval_report.py          # 从 JSON 生成 Markdown 评测报告
│   ├── generate_comparison_report.py    # 生成对比 Markdown 报告
│   └── ...
│
├── heading_analysis/
│   ├── extract_bad_heading_cases.py     # 提取 heading 误差大的案例
│   ├── visualize_heading_errors.py      # 可视化 heading 误差BEV/图像/极坐标)
│   └── ...
│
├── visualization/
│   └── test_val_visualize_from_paths.py # 从路径可视化检测结果
│
├── utilities/
│   ├── check_img_exists.py              # 检查图像文件是否存在
│   └── extract_video_frames.py          # 视频帧提取
│
└── docs/                                # 详细设计文档(本文件所在目录)

3. 核心流程

单模型评测(run_eval_with_config.sh

┌─────────────────────────────────────────────────────┐
│  run_eval_with_config.sh                            │
│                                                     │
│  1. 设置 PYTHONPATH                                  │
│  2. 指定配置文件路径 (MODEL_CONFIG)                   │
│  3. 指定输出目录  (OUTPUT_BASE/MODEL_NAME/TIMESTAMP) │
│  4. 调用 eval_tools/core/eval.py                    │
└─────────────────────────────────────────────────────┘
                        │
                        ▼
┌─────────────────────────────────────────────────────┐
│  eval.py                                            │
│                                                     │
│  1. 解析 YAML 配置 + 命令行参数                       │
│  2. 初始化 Evaluator含 ROIProcessor              │
│  3. 加载检测结果 & 真值文件对                         │
│  4. 并行处理每张图 (IoU 匹配 + 指标统计)              │
│  5. 汇总指标并生成报告                                │
└─────────────────────────────────────────────────────┘
                        │
           ┌────────────┴─────────────┐
           ▼                          ▼
  evaluation_report.json      detailed_3d_matches.json
  evaluation_report.txt       (--save-detailed-matches)
  per_case_reports/

双模型对比(compare_models_with_common_matches.sh

Model 1 评测 → detailed_3d_matches.json
                                        ┐
                                        ├─ find_common_matches.py → common_matches.json
                                        │
Model 2 评测 → detailed_3d_matches.json ┘
                                        │
                                        └─ compare_models.py → 对比报告

4. 配置文件说明

配置文件位于 eval_tools/configs/YAML 格式,分以下几个部分:

4.1 数据集路径 (dataset)

dataset:
  det_path: "/data1/.../evalset_roi0"  # 检测结果根目录(含 case 文件夹)
  gt_path:  "/data1/xdzhu/Testdata"    # 真值标签根目录(含 case 文件夹)
  path_depth: 1       # 目录层级1 = det_path/case/txt_results
                      #           2 = det_path/level1/case/txt_results
  det_format: "json"  # 检测结果格式auto / json / txt
  gt_format:  "json"  # 真值格式auto / json / txt

目录结构要求(path_depth: 1

det_path/
└── case_019b178d/
    └── json_results/   ← det_format="json"
        ├── 000000.json
        └── 000001.json

gt_path/
└── case_019b178d/
    └── labels_json/    ← gt_format="json"
        ├── 000000.json
        └── 000001.json

4.2 图像尺寸 (image)

image:
  width:  1920
  height: 1080

4.3 模型配置与 GT 过滤 (model)

model:
  input_size: 704               # 模型输入宽度(像素)
  min_box_size_at_input_scale: 8  # 模型输入分辨率下的最小框尺寸
  # GT 过滤阈值自动计算min_box_size = 8 * roi_width / 704
  # ROI0 (1920→704): ≈ 21.8 像素ROI1 (704→704): 8 像素

4.4 并行性能 (performance)

performance:
  num_workers: 32   # 并行 worker 数null = auto-detect CPU 核数)

4.5 ROI GT 处理 (roi_gt)

roi_gt:
  enabled: true
  calib_root: "/data1/xdzhu/Testdata"  # 标定文件根目录(含 camera4.json
  roi_config: [1920, 960]              # ROI 配置,与训练保持一致
  # ROI0: [1920, 960]
  # ROI1: [704, 352]

重要roi_config 必须与训练时的 ROI 配置完全一致否则坐标系不对齐IoU 计算将不准确。

4.6 类别定义 (classes)

classes:
  3d_classes: [0, 1, 2, 3]    # 参与 3D 评测的类别
  2d_classes: [4, 5, ..., 13]  # 仅参与 2D 评测的类别
  class_names:
    0: "vehicle"
    1: "pedestrian"
    ...
    13: "tricycle"

4.7 匹配参数 (matching)

matching:
  iou_threshold: 0.5   # 2D 匹配 IoU 阈值

4.8 2D 指标 (metrics_2d)

metrics_2d:
  enabled: true
  conf_threshold: 0.4      # Precision/Recall 置信度阈值
  ap_method: "voc2010"     # AP 计算方法voc201011点插值/ coco全点插值

4.9 3D 指标 (metrics_3d)

metrics_3d:
  enabled: true
  heading_tolerance: "both"  # strict / relaxed / both
  distance_ranges:           # 纵向距离区间(米)
    - [0, 10]
    - [10, 20]
    - ...
    - [100, 999]
  lateral_distance_ranges:   # 横向距离区间x 轴)
    - [-50, -40]
    - ...
    - [40, 50]

heading_tolerance 说明

含义
strict 标准计算(默认)
relaxed 对称物体允许 180° 对称:error = min(error, π - error)
both 同时计算并输出 strict 和 relaxed 两套结果

4.10 输出配置 (output)

output:
  save_path: "evaluation_results/my_model/{timestamp}"
  formats: ["json", "txt"]
  print_details: true
  per_case_reports: true

5. 命令行参数说明

eval_tools/core/eval.py 支持以下参数(命令行参数优先级高于配置文件):

参数 类型 默认值 说明
--config str YAML 配置文件路径
--det-path str 检测结果根目录
--gt-path str 真值标签根目录
--path-depth int 1 目录层级1 或 2
--det-format str auto 检测结果格式auto/json/txt
--gt-format str auto 真值格式auto/json/txt
--output-dir str eval_results 输出目录
--img-width int 1920 图像宽度(像素)
--img-height int 1080 图像高度(像素)
--iou-threshold float 0.5 IoU 匹配阈值
--conf-threshold float 0.5 置信度阈值
--ap-method str voc2010 AP 计算方法voc2010/coco
--heading-tolerance str strict heading 容忍模式strict/relaxed/both
--num-workers int auto 并行 worker 数
--eval-2d-only flag 仅评测 2D
--eval-3d-only flag 仅评测 3D
--save-detailed-matches flag 保存详细 3D 匹配信息(供模型对比使用)

6. 数据格式

6.1 真值Ground Truth格式

车辆类别50 个值)

[class, x, y, w, h,                          # 0-4: 类别 + 归一化 2D 框
 x3d, y3d, z3d,                              # 5-7: 3D 中心点(相机坐标系)
 l, h, w,                                   # 8-10: 3D 尺寸(长高宽)
 rot_y,                                      # 11: 绕 Y 轴旋转角
 xc, yc,                                     # 12-13: 3D 中心点的图像投影
 xc_d, yc_d,                                 # 14-15: 深度相关投影
 alpha,                                      # 16: 观测角
 0,                                          # 17: 占位符
 前面(x3d,y3d,z3d,alpha,xc,yc,score,occ),    # 18-25
 后面(x3d,y3d,z3d,alpha,xc,yc,score,occ),    # 26-33
 左面(x3d,y3d,z3d,alpha,xc,yc,score,occ),    # 34-41
 右面(x3d,y3d,z3d,alpha,xc,yc,score,occ)]    # 42-49

行人/自行车/骑手18 个值) 上述 0-17无四面信息。

仅 2D 标注6 个值)

[class, x, y, w, h, -1]

6.2 检测结果格式

车辆15 个字段)

vehicle  0.95  368.08 574.17 437.89 617.20  cam  -30.14 1.43 68.55  5.52 2.50 2.31  2.70  left
label    conf  x1     y1     x2     y2       cs   x3d    y3d  z3d    l    h    w     rot_y face_type

face_type 取值:front / back(或 rear/tail/ left / right

行人/骑手等15 个字段):同上,face_type 固定为 whole

纯 2D 类别6 个字段)

plate  0.94246  532.12 203.26 558.73 214.86
label  conf     x1     y1     x2     y2

7. 评测指标

7.1 2D 检测指标

  • PrecisionTP / (TP + FP),按 conf_threshold 过滤
  • RecallTP / (TP + FN)
  • F1-Score2 × P × R / (P + R)
  • APPR 曲线下面积IoU 阈值 0.5
  • mAP:所有类别 AP 的算术平均

匹配规则

  1. 按置信度从高到低排序预测框
  2. 与真值框 IoU ≥ 0.5 且类别相同 → TP每个真值框只匹配一次
  3. 未匹配预测框 → FP未被匹配真值框 → FN

类别划分14 类)

ID 类别 3D 评测
0 vehicle
1 pedestrian
2 bicycle
3 rider
4 roadblock
5 head
6 tsr
7 guideboard
8 plate
9 wheel
10 tl_border
11 tl_wick
12 tl_num
13 tricycle

7.2 3D 检测指标

前提2D IoU 匹配成功(≥ 0.5)且真值包含完整 3D 标注。

车辆类别(基于最近面中心点对比):

根据检测结果的 face_type 字段,在真值中选取对应面的中心点进行比较:

face_type → 真值面中心点索引
  front  →  [18, 19, 20]  (x3d, y3d, z3d)
  back   →  [26, 27, 28]
  left   →  [34, 35, 36]
  right  →  [42, 43, 44]

行人/骑手/自行车:使用整体中心点 [5, 6, 7] 进行比较。

误差指标

  • 横向误差Lateral Error|x3d_pred - x3d_gt|(米)
  • 纵向误差Longitudinal Error|z3d_pred - z3d_gt|(米)
  • Heading 误差|rot_y_pred - rot_y_gt|(弧度)

每个指标输出均值Mean、中位数Median、标准差Std、90 百分位数P90


8. ROI GT 处理

动机

训练时图像经过 ROI 裁剪和缩放(坐标系改变),但历史评测代码中检测结果在 ROI 坐标系GT 在原图坐标系,导致 IoU 计算不准确。

解决方案

ROIProcessoreval_tools/evaluator/roi_processor.py)在评测时对 GT 标签执行与训练完全相同的 ROI 处理:

  1. 读取标定文件(case_root/camera4.json)中的 focal_u, focal_v, cu, cv, pitch
  2. 计算裁剪中心:cx = oriW // 2cy = cv - focal_v × tan(pitch × π/180)
  3. (cx, cy) 为中心按 roi_config 裁剪 ROI
  4. 过滤完全在 ROI 外的目标;将部分在 ROI 内的框 clip 到边界
  5. 将坐标转换到 ROI 相对坐标系 → 再缩放到模型输入分辨率

配置对应关系

训练 ROI 配置 roi_config
ROI0大 crop [1920, 960]
ROI1小 crop [704, 352]

9. 模型对比(共同匹配集)

问题背景

直接比较两个模型的 3D 指标时,若双方匹配到的 GT 对象数量不同(如相差 11.7%),差异可能来自匹配集差异而非模型质量。

解决方案

只统计两个模型都成功匹配的 GT 对象Common Matches的 3D 指标。

使用方式

方式一:一键脚本(推荐)

bash eval_tools/model_comparison/compare_models_with_common_matches.sh

该脚本自动完成:

  1. 评测 Model 1保存 detailed_3d_matches.json
  2. 评测 Model 2保存 detailed_3d_matches.json
  3. 调用 find_common_matches.py 得到 common_matches.json
  4. 调用 compare_models.py 生成对比报告
  5. 调用 generate_eval_report.py 为各模型生成 Markdown 报告

方式二:手动分步执行

# Step 1: 评测两个模型
python eval_tools/core/eval.py \
  --config eval_tools/configs/eval_config_mono3d-roi1.yaml \
  --output-dir eval_results/model1 \
  --heading-tolerance both \
  --save-detailed-matches

python eval_tools/core/eval.py \
  --config eval_tools/configs/eval_config_yolov5s_cncap-roi1.yaml \
  --output-dir eval_results/model2 \
  --heading-tolerance both \
  --save-detailed-matches

# Step 2: 找出共同匹配
python eval_tools/model_comparison/find_common_matches.py \
  --model1-matches eval_results/model1/detailed_3d_matches.json \
  --model2-matches eval_results/model2/detailed_3d_matches.json \
  --output eval_results/common_matches.json \
  --model1-name "mono3d" \
  --model2-name "yolov5s-300w"

# Step 3: 生成对比报告
python eval_tools/model_comparison/compare_models.py \
  --model1 eval_results/model1/evaluation_report.json \
  --model2 eval_results/model2/evaluation_report.json \
  --common-matches eval_results/common_matches.json \
  --output-dir eval_results/comparison \
  --model1-name "mono3d" \
  --model2-name "yolov5s-300w"

生成 Markdown 报告

python eval_tools/model_comparison/generate_eval_report.py \
  eval_results/model1/evaluation_report.json \
  --model "yolov5s-300w-cncap" \
  --date 2026-03-03

输出:eval_results/model1/EVALUATION_REPORT.md


10. Heading 误差分析

对于 heading 预测较差的案例,可使用以下工具进行深入分析:

Step 1提取 bad cases

python eval_tools/heading_analysis/extract_bad_heading_cases.py \
  --input eval_results/model1/detailed_3d_matches.json \
  --threshold 1.5 \      # heading 误差阈值(弧度)
  --top-k 100 \
  --output bad_heading.json \
  --stats

Step 2可视化

python eval_tools/heading_analysis/visualize_heading_errors.py \
  --input bad_heading.json \
  --image-root /path/to/images \
  --output runs/heading_viz \
  --viz-types bev image angle combined

可视化类型:

  • bev鸟瞰图GT / Pred 的 3D 框 + 方向箭头)
  • image原图视图2D 框 + 误差标注)
  • angle:角度分析(极坐标 + 柱状图)
  • combined:四宫格综合视图

11. 输出结果

11.1 文件列表

文件 说明
evaluation_report.json 完整评测报告JSON 格式,含所有类别和距离区间)
evaluation_report.txt 人类可读的文本报告
detailed_3d_matches.json 每帧每目标的 3D 匹配详情(--save-detailed-matches
per_case_reports/*.json 每个 case 的独立报告(per_case_reports: true
EVALUATION_REPORT.md Markdown 格式摘要报告(由 generate_eval_report.py 生成)

11.2 JSON 报告结构

{
  "evaluation_config": {...},
  "2d_evaluation": {
    "overall": {
      "precision": 0.85,
      "recall": 0.78,
      "f1_score": 0.81,
      "map": 0.72
    },
    "per_class": {
      "vehicle": {"precision": ..., "recall": ..., "ap": ...},
      ...
    }
  },
  "3d_evaluation": {
    "vehicle": {
      "overall": {
        "n_samples": 440408,
        "lateral_mean": 0.647,
        "longitudinal_mean": 1.680,
        "heading_mean_strict": 0.258
      },
      "by_distance": {
        "[0-10m]": {...},
        ...
      }
    }
  }
}

11.3 控制台输出示例

3D Metrics:
  vehicle [overall]: Lat=0.647m, Long=1.680m, Head=0.258rad (n=440408)
    [0-10m]:   Lat=0.423m, Long=0.891m, Head=0.153rad (n=98241)
    [10-20m]:  Lat=0.501m, Long=1.203m, Head=0.177rad (n=142038)
    [30-60m]:  Lat=1.149m, Long=5.074m, Head=0.607rad (n=18432)
    [100-999m]:Lat=2.341m, Long=9.221m, Head=1.036rad (n=871)

12. 使用示例

例 1单模型评测当前默认入口

cd /deeplearning_team/ydong/dongying/projects/yolov5-3d
conda activate slot

bash eval_tools/core/run_eval_with_config.sh

脚本使用 eval_tools/configs/eval_config_yolov5s_cncap-roi0.yaml,结果保存至:

evaluation_results/eval_results_common_match_comparison_cncap_yolov5s_20260303_roi0/
└── yolov5s-300w-newdata-cncap-test/
    └── 20260303_HHMMSS/
        ├── evaluation_report.json
        ├── evaluation_report.txt
        └── detailed_3d_matches.json

例 2命令行直接评测不使用配置文件

python eval_tools/core/eval.py \
  --det-path /data1/.../inference_results/model/evalset_roi0 \
  --gt-path  /data1/xdzhu/Testdata \
  --output-dir evaluation_results/my_test \
  --heading-tolerance both \
  --conf-threshold 0.4 \
  --num-workers 16

例 3仅 2D 评测

python eval_tools/core/eval.py \
  --config eval_tools/configs/eval_config_yolov5s_cncap-roi0.yaml \
  --eval-2d-only \
  --output-dir evaluation_results/2d_only_test

例 4双模型对比

bash eval_tools/model_comparison/compare_models_with_common_matches.sh

例 5修改配置直接运行

仅修改 run_eval_with_config.sh 中的以下三个变量即可适配新模型:

MODEL_CONFIG="eval_tools/configs/eval_config_yolov5s_cncap-roi0.yaml"
OUTPUT_BASE="evaluation_results/eval_results_my_model"
MODEL_NAME="my-model-name"

13. 常见问题

Q1No image pairs found

原因det_pathgt_path 下的 case 名称不匹配,或 det_format / gt_format 设置错误。

排查

ls ${det_path}/        # 查看 case 目录名
ls ${det_path}/case_xxx/  # 查看是 json_results/ 还是 txt_results/

Q2IoU 始终为 0评测指标异常

原因roi_gt 配置未启用,或 roi_config 与训练时不匹配,导致坐标系不对齐。

排查:检查配置中 roi_gt.enabled: trueroi_config 与训练 YAML 中的 roi: 字段一致。

Q33D 指标样本数 (n=0)

原因:真值中该类别无完整 3D 标注(仅有 6 维的 2D-only 标注),或 2D 匹配 IoU < 0.5。

Q4如何添加新模型配置

复制现有配置文件,仅修改 dataset.det_pathdataset.gt_path 即可:

cp eval_tools/configs/eval_config_yolov5s_cncap-roi0.yaml \
   eval_tools/configs/eval_config_my_model-roi0.yaml
# 编辑新文件中的 det_path 和 output.save_path

Q5如何加速评测

调大 performance.num_workers(建议不超过 CPU 核数 × 2

python eval_tools/core/eval.py --config ... --num-workers 64

文档生成日期2026-03-03