333 lines
10 KiB
Markdown
333 lines
10 KiB
Markdown
|
|
# 基于共同匹配集的3D指标对比 - 实现总结
|
|||
|
|
|
|||
|
|
## 实现概述
|
|||
|
|
|
|||
|
|
已完成基于共同匹配集的3D指标对比功能,解决了两个模型匹配样本数量不一致导致无法公平对比的问题。
|
|||
|
|
|
|||
|
|
## 核心实现
|
|||
|
|
|
|||
|
|
### 1. 评测器扩展 (evaluator.py)
|
|||
|
|
|
|||
|
|
**修改内容**:
|
|||
|
|
- 添加 `save_detailed_matches` 参数到 `__init__()` 方法
|
|||
|
|
- 添加 `detailed_3d_matches` 存储结构
|
|||
|
|
- 修改 `_process_frame_3d()` 保存每个匹配对的详细信息:
|
|||
|
|
* GT唯一ID (基于bbox坐标的MD5哈希)
|
|||
|
|
* GT和检测的2D bbox
|
|||
|
|
* GT和检测的3D中心点
|
|||
|
|
* IoU和置信度
|
|||
|
|
* 3D误差(lateral、longitudinal、heading)
|
|||
|
|
* 距离信息(用于区间统计)
|
|||
|
|
- 在 `evaluate_3d()` 中聚合详细匹配数据(支持多进程)
|
|||
|
|
- 在 `generate_report()` 中保存 `detailed_3d_matches.json`
|
|||
|
|
|
|||
|
|
**输出文件**:
|
|||
|
|
- `detailed_3d_matches.json` - 包含所有匹配对的详细信息
|
|||
|
|
|
|||
|
|
### 2. 共同匹配查找工具 (find_common_matches.py)
|
|||
|
|
|
|||
|
|
**功能**:
|
|||
|
|
- 加载两个模型的详细匹配数据
|
|||
|
|
- 基于GT唯一ID找出共同匹配的目标
|
|||
|
|
- 计算匹配统计(总数、共同、独有)
|
|||
|
|
- 基于共同匹配重新计算3D统计
|
|||
|
|
- 生成详细的统计报告
|
|||
|
|
|
|||
|
|
**核心函数**:
|
|||
|
|
- `find_common_matches()` - 找出共同匹配
|
|||
|
|
- `recompute_3d_stats_from_common_matches()` - 重新计算3D统计
|
|||
|
|
- `print_statistics()` - 打印匹配统计
|
|||
|
|
|
|||
|
|
**输出文件**:
|
|||
|
|
- `common_matches.json` - 包含共同匹配索引和重新计算的统计
|
|||
|
|
|
|||
|
|
### 3. 模型比较器扩展 (compare_models.py)
|
|||
|
|
|
|||
|
|
**修改内容**:
|
|||
|
|
- `__init__()` 添加 `common_matches_data` 参数
|
|||
|
|
- `compare_3d_metrics()` 检测是否使用共同匹配
|
|||
|
|
- 新增 `_compare_3d_metrics_common_matches()` 方法:
|
|||
|
|
* 使用预计算的共同匹配统计
|
|||
|
|
* 显示匹配统计摘要
|
|||
|
|
* 生成基于共同匹配的对比
|
|||
|
|
- `main()` 添加 `--common-matches` 参数
|
|||
|
|
|
|||
|
|
**使用方式**:
|
|||
|
|
```bash
|
|||
|
|
# 不使用共同匹配(传统方式)
|
|||
|
|
python eval_tools/compare_models.py --model1 m1.json --model2 m2.json
|
|||
|
|
|
|||
|
|
# 使用共同匹配
|
|||
|
|
python eval_tools/compare_models.py \
|
|||
|
|
--model1 m1.json --model2 m2.json \
|
|||
|
|
--common-matches common_matches.json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 评测脚本扩展 (eval.py)
|
|||
|
|
|
|||
|
|
**修改内容**:
|
|||
|
|
- 添加 `--save-detailed-matches` 参数
|
|||
|
|
- 传递参数到 Evaluator 构造函数
|
|||
|
|
- 在输出中显示是否保存详细匹配
|
|||
|
|
|
|||
|
|
**使用方式**:
|
|||
|
|
```bash
|
|||
|
|
# 普通评测
|
|||
|
|
python eval_tools/eval.py --config config.yaml
|
|||
|
|
|
|||
|
|
# 保存详细匹配
|
|||
|
|
python eval_tools/eval.py --config config.yaml --save-detailed-matches
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5. 完整流程脚本 (compare_models_with_common_matches.sh)
|
|||
|
|
|
|||
|
|
**功能**:
|
|||
|
|
自动化执行完整流程:
|
|||
|
|
1. 评测 Model 1 并保存详细匹配
|
|||
|
|
2. 评测 Model 2 并保存详细匹配
|
|||
|
|
3. 找出共同匹配
|
|||
|
|
4. 生成基于共同匹配的对比报告
|
|||
|
|
5. 生成传统对比报告(用于参考)
|
|||
|
|
|
|||
|
|
**使用方式**:
|
|||
|
|
```bash
|
|||
|
|
bash eval_tools/compare_models_with_common_matches.sh
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 工作流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────┐
|
|||
|
|
│ Model 1 Eval │
|
|||
|
|
│ + save-detailed-matches │
|
|||
|
|
└────────────┬────────────┘
|
|||
|
|
│ detailed_3d_matches.json
|
|||
|
|
│
|
|||
|
|
↓
|
|||
|
|
┌─────────────────────────┐
|
|||
|
|
│ find_common_matches.py │←──┐
|
|||
|
|
└─────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ common_matches.json │ detailed_3d_matches.json
|
|||
|
|
│ │
|
|||
|
|
↓ │
|
|||
|
|
┌─────────────────────────┐ │
|
|||
|
|
│ compare_models.py │ │
|
|||
|
|
│ --common-matches │ │
|
|||
|
|
└─────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
↓ │
|
|||
|
|
comparison_report.txt │
|
|||
|
|
(based on common matches) │
|
|||
|
|
│
|
|||
|
|
┌─────────────────────────┐ │
|
|||
|
|
│ Model 2 Eval │ │
|
|||
|
|
│ + save-detailed-matches │─────────┘
|
|||
|
|
└─────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 数据结构
|
|||
|
|
|
|||
|
|
### detailed_3d_matches.json
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"case_name": {
|
|||
|
|
"frame_name": {
|
|||
|
|
"class_name": [
|
|||
|
|
{
|
|||
|
|
"gt_id": "unique_hash",
|
|||
|
|
"gt_bbox": [x1, y1, x2, y2],
|
|||
|
|
"gt_center_3d": [x, y, z],
|
|||
|
|
"det_bbox": [x1, y1, x2, y2],
|
|||
|
|
"det_center_3d": [x, y, z],
|
|||
|
|
"iou": 0.89,
|
|||
|
|
"confidence": 0.87,
|
|||
|
|
"errors": {
|
|||
|
|
"lateral": 0.12,
|
|||
|
|
"longitudinal": 0.15,
|
|||
|
|
"heading": 0.05
|
|||
|
|
},
|
|||
|
|
"distance": {
|
|||
|
|
"longitudinal": 8.20,
|
|||
|
|
"lateral": -7.13
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### common_matches.json
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"match_statistics": {
|
|||
|
|
"model1_total": 440408,
|
|||
|
|
"model2_total": 491768,
|
|||
|
|
"common": 425163,
|
|||
|
|
"model1_unique": 15245,
|
|||
|
|
"model2_unique": 66605,
|
|||
|
|
"common_percentage_of_model1": 96.5,
|
|||
|
|
"per_class": { ... }
|
|||
|
|
},
|
|||
|
|
"common_matches": {
|
|||
|
|
"case_name": {
|
|||
|
|
"frame_name": {
|
|||
|
|
"class_name": [
|
|||
|
|
{
|
|||
|
|
"gt_id": "unique_hash",
|
|||
|
|
"model1_idx": 0,
|
|||
|
|
"model2_idx": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"model1_3d_stats": {
|
|||
|
|
"vehicle": {
|
|||
|
|
"num_samples": 425163,
|
|||
|
|
"lateral_error": {"mean": 1.3251, "std": 0.8745, ...},
|
|||
|
|
"longitudinal_error": {"mean": 2.5892, "std": 1.2341, ...},
|
|||
|
|
"heading_error": {"mean": 0.2256, "std": 0.1234, ...}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"model2_3d_stats": { ... },
|
|||
|
|
"model_names": {
|
|||
|
|
"model1": "mono3d",
|
|||
|
|
"model2": "yolov5s-300w"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 使用示例
|
|||
|
|
|
|||
|
|
### 示例1:完整流程(推荐)
|
|||
|
|
```bash
|
|||
|
|
bash eval_tools/compare_models_with_common_matches.sh
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 示例2:手动步骤
|
|||
|
|
```bash
|
|||
|
|
# 步骤1:评测并保存详细匹配
|
|||
|
|
python eval_tools/eval.py \
|
|||
|
|
--config eval_tools/configs/eval_config_mono3d.yaml \
|
|||
|
|
--save-detailed-matches
|
|||
|
|
|
|||
|
|
python eval_tools/eval.py \
|
|||
|
|
--config eval_tools/configs/eval_config_yolov5.yaml \
|
|||
|
|
--save-detailed-matches
|
|||
|
|
|
|||
|
|
# 步骤2:找出共同匹配
|
|||
|
|
python eval_tools/find_common_matches.py \
|
|||
|
|
--model1-matches eval_results/model1/detailed_3d_matches.json \
|
|||
|
|
--model2-matches eval_results/model2/detailed_3d_matches.json \
|
|||
|
|
--output common_matches.json
|
|||
|
|
|
|||
|
|
# 步骤3:比较(基于共同匹配)
|
|||
|
|
python eval_tools/compare_models.py \
|
|||
|
|
--model1 eval_results/model1/evaluation_report.json \
|
|||
|
|
--model2 eval_results/model2/evaluation_report.json \
|
|||
|
|
--common-matches common_matches.json \
|
|||
|
|
--output-dir comparison_results
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 对比报告示例
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
================================================================================
|
|||
|
|
3D METRICS COMPARISON (COMMON MATCHES ONLY)
|
|||
|
|
================================================================================
|
|||
|
|
|
|||
|
|
Match Statistics:
|
|||
|
|
mono3d Total Matches: 440,408
|
|||
|
|
yolov5s-300w Total Matches: 491,768
|
|||
|
|
Common Matches: 425,163 (96.5% of mono3d)
|
|||
|
|
mono3d Unique: 15,245 (3.5%)
|
|||
|
|
yolov5s-300w Unique: 66,605 (13.5%)
|
|||
|
|
|
|||
|
|
VEHICLE (Common Matches: 425,163):
|
|||
|
|
Metric mono3d yolov5s-300w Diff Change %
|
|||
|
|
------------------------------------------------------------------------------------
|
|||
|
|
Lateral (m) 1.3251 1.2103 -0.1148 -8.66% ✓
|
|||
|
|
Longitudinal (m) 2.5892 2.4231 -0.1661 -6.42% ✓
|
|||
|
|
Heading (rad) 0.2256 0.3098 +0.0842 +37.32% ✗
|
|||
|
|
|
|||
|
|
Note: 这些统计基于两个模型都成功匹配的目标,排除了只被一个模型匹配的目标。
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 关键优势
|
|||
|
|
|
|||
|
|
1. **公平对比**:只比较相同目标的3D预测质量,排除召回率差异的影响
|
|||
|
|
2. **问题诊断**:识别哪些目标一个模型能匹配而另一个不能
|
|||
|
|
3. **性能分析**:可以单独分析各模型独有匹配的特点
|
|||
|
|
4. **向后兼容**:不影响现有评测流程,可选启用
|
|||
|
|
5. **灵活性**:支持传统对比和共同匹配对比两种模式
|
|||
|
|
|
|||
|
|
## 性能考虑
|
|||
|
|
|
|||
|
|
- **存储开销**:`detailed_3d_matches.json` 约为 `evaluation_report.json` 的 5-10 倍
|
|||
|
|
- **时间开销**:保存详细匹配会增加约 5-10% 的评测时间
|
|||
|
|
- **建议**:只在需要对比时使用 `--save-detailed-matches`
|
|||
|
|
|
|||
|
|
## 文件清单
|
|||
|
|
|
|||
|
|
### 新增文件
|
|||
|
|
1. `eval_tools/find_common_matches.py` - 共同匹配查找工具
|
|||
|
|
2. `eval_tools/compare_models_with_common_matches.sh` - 完整流程脚本
|
|||
|
|
3. `eval_tools/COMMON_MATCH_COMPARISON_DESIGN.md` - 设计方案文档
|
|||
|
|
4. `eval_tools/COMMON_MATCH_COMPARISON_USAGE.md` - 使用指南
|
|||
|
|
5. `eval_tools/COMMON_MATCH_COMPARISON_SUMMARY.md` - 本文档
|
|||
|
|
|
|||
|
|
### 修改文件
|
|||
|
|
1. `eval_tools/evaluator/evaluator.py` - 添加详细匹配保存功能
|
|||
|
|
2. `eval_tools/compare_models.py` - 添加共同匹配对比功能
|
|||
|
|
3. `eval_tools/eval.py` - 添加 `--save-detailed-matches` 参数
|
|||
|
|
|
|||
|
|
## 测试建议
|
|||
|
|
|
|||
|
|
建议进行以下测试:
|
|||
|
|
|
|||
|
|
1. **功能测试**:
|
|||
|
|
```bash
|
|||
|
|
bash eval_tools/compare_models_with_common_matches.sh
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. **验证测试**:
|
|||
|
|
- 检查 `detailed_3d_matches.json` 是否正确生成
|
|||
|
|
- 检查共同匹配数量是否合理
|
|||
|
|
- 验证对比报告中的统计是否基于共同匹配
|
|||
|
|
|
|||
|
|
3. **性能测试**:
|
|||
|
|
- 对比启用/不启用 `--save-detailed-matches` 的评测时间
|
|||
|
|
- 检查文件大小是否在预期范围内
|
|||
|
|
|
|||
|
|
## 下一步扩展(可选)
|
|||
|
|
|
|||
|
|
1. **独有匹配分析**:
|
|||
|
|
- 分析独有匹配的特征(距离、大小、置信度等)
|
|||
|
|
- 生成独有匹配的可视化
|
|||
|
|
|
|||
|
|
2. **距离区间对比**:
|
|||
|
|
- 支持基于共同匹配的距离区间统计
|
|||
|
|
- 横向/纵向距离区间的共同匹配对比
|
|||
|
|
|
|||
|
|
3. **可视化工具**:
|
|||
|
|
- 共同匹配 vs 独有匹配的分布图
|
|||
|
|
- 不同距离/位置的共同匹配率热力图
|
|||
|
|
|
|||
|
|
4. **性能优化**:
|
|||
|
|
- 使用更高效的序列化格式(如 MessagePack)
|
|||
|
|
- 按需加载详细匹配数据
|
|||
|
|
|
|||
|
|
## 总结
|
|||
|
|
|
|||
|
|
已成功实现基于共同匹配集的3D指标对比功能,解决了两个模型匹配样本数量不一致的问题。该方案:
|
|||
|
|
|
|||
|
|
- ✅ 确保公平对比相同目标的3D性能
|
|||
|
|
- ✅ 提供独有匹配的统计分析
|
|||
|
|
- ✅ 保持向后兼容性
|
|||
|
|
- ✅ 提供完整的自动化流程
|
|||
|
|
- ✅ 包含详细的使用文档
|
|||
|
|
|
|||
|
|
可以立即使用此功能进行模型对比分析。
|