# 基于共同匹配集的3D指标对比 - 使用指南

## 问题背景

在比较两个模型的3D检测性能时，发现两个模型匹配到的样本数量不一致：

```
Model A: 匹配了 440,408 个 vehicle
Model B: 匹配了 491,768 个 vehicle
差异: 51,360 个样本 (11.7%)
```

**问题**：无法确定性能差异是因为模型质量不同，还是因为匹配了不同的目标。

**解决方案**：只比较两个模型都成功匹配到GT的目标，确保对比的是相同目标的3D性能。

## 快速开始

### 方法一：使用一键脚本（推荐）

```bash
bash eval_tools/compare_models_with_common_matches.sh
```

这个脚本会自动完成以下步骤：
1. 评测 Model 1（mono3d）并保存详细匹配
2. 评测 Model 2（yolov5s）并保存详细匹配
3. 找出共同匹配的GT目标
4. 生成基于共同匹配的对比报告
5. 生成传统对比报告（用于参考）

### 方法二：手动执行步骤

#### 步骤1：评测模型并保存详细匹配

```bash
# 评测 Model 1
python eval_tools/eval.py \
  --config eval_tools/configs/eval_config_mono3d.yaml \
  --save-detailed-matches

# 评测 Model 2
python eval_tools/eval.py \
  --config eval_tools/configs/eval_config_yolov5.yaml \
  --save-detailed-matches
```

**输出文件**：
- `evaluation_report.json` - 评测报告
- `detailed_3d_matches.json` - 详细匹配信息（新增）

#### 步骤2：找出共同匹配

```bash
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 \
  --model1-name "mono3d" \
  --model2-name "yolov5s-300w"
```

**输出示例**：
```
================================================================================
COMMON MATCH STATISTICS
================================================================================

Overall:
  Model 1 Total Matches: 440,408
  Model 2 Total Matches: 491,768
  Common Matches: 425,163 (96.5% of Model 1)
  Model 1 Unique: 15,245 (3.5%)
  Model 2 Unique: 66,605 (13.5%)

Per-Class Statistics:
Class           Model1     Model2     Common    Common%   M1 Unique   M2 Unique
--------------------------------------------------------------------------------
vehicle        440,408    491,768    425,163      96.5%       15,245      66,605
```

#### 步骤3：比较模型（基于共同匹配）

```bash
python eval_tools/compare_models.py \
  --model1 eval_results/model1/evaluation_report.json \
  --model2 eval_results/model2/evaluation_report.json \
  --model1-name "mono3d" \
  --model2-name "yolov5s-300w" \
  --common-matches common_matches.json \
  --output-dir comparison_common_matches
```

**关键参数**：
- `--common-matches`: 指定共同匹配数据文件
- 如果不提供此参数，将使用传统方式比较（所有匹配）

## 对比报告解读

### 共同匹配对比报告

```
================================================================================
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
  yolov5s-300w Unique: 66,605

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. **匹配统计**：
   - Common Matches: 两个模型都匹配到的GT数量
   - Model Unique: 只被该模型匹配的GT数量
   - Common%: 共同匹配占该模型总匹配的百分比

2. **3D误差对比**：
   - 基于相同的GT目标进行比较
   - 可以公平评估两个模型的3D预测质量
   - ✓ 表示model2更好，✗ 表示model1更好

3. **独有匹配分析**：
   - Model 1 Unique: 15,245 (3.5%)
     * 这些是只有model1匹配到的目标
     * 可能是容易匹配的目标
   - Model 2 Unique: 66,605 (13.5%)
     * 这些是只有model2匹配到的目标
     * 说明model2的召回率更高

## 数据文件说明

### detailed_3d_matches.json

保存每个匹配对的详细信息：

```json
{
  "case_019b178d": {
    "frame_000018": {
      "vehicle": [
        {
          "gt_id": "a1b2c3d4e5f6g7h8",
          "gt_bbox": [90.48, 561.98, 241.52, 714.00],
          "gt_center_3d": [-7.13, 0.91, 8.20],
          "det_bbox": [91.2, 562.5, 240.8, 713.2],
          "det_center_3d": [-7.25, 0.89, 8.35],
          "iou": 0.89,
          "confidence": 0.87478,
          "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,
    "common_percentage_of_model1": 96.5
  },
  "model1_3d_stats": {
    "vehicle": {
      "num_samples": 425163,
      "lateral_error": {"mean": 1.3251, "std": 0.8745},
      "longitudinal_error": {"mean": 2.5892, "std": 1.2341}
    }
  },
  "model2_3d_stats": { ... }
}
```

## 使用场景

### 场景1：公平对比两个模型的3D性能

**问题**：两个模型召回率不同，匹配的目标不一样。

**方案**：使用共同匹配对比，确保比较相同目标的预测质量。

```bash
# 使用 --common-matches 参数
python eval_tools/compare_models.py \
  --model1 model1_report.json \
  --model2 model2_report.json \
  --common-matches common_matches.json \
  --output-dir fair_comparison
```

### 场景2：分析模型独有匹配的特点

**问题**：想知道为什么一个模型能匹配更多目标。

**方案**：查看 common_matches.json 中的统计信息。

```python
import json

with open('common_matches.json') as f:
    data = json.load(f)

stats = data['match_statistics']
print(f"Model 1 Unique: {stats['model1_unique']}")
print(f"Model 2 Unique: {stats['model2_unique']}")

# 可以进一步分析独有匹配的距离分布、置信度等
```

### 场景3：对比不同训练策略的效果

**问题**：调整了训练参数，想知道3D精度是否真的提升。

**方案**：基于共同匹配对比，排除召回率变化的影响。

## 注意事项

1. **存储开销**：
   - `detailed_3d_matches.json` 约为 `evaluation_report.json` 的 5-10 倍
   - 建议只在需要对比时使用 `--save-detailed-matches`

2. **GT唯一标识**：
   - 基于2D bbox坐标生成MD5哈希
   - 确保同一个GT在两个模型中有相同的ID

3. **向后兼容**：
   - 不使用 `--save-detailed-matches` 时，行为与之前完全一致
   - 不使用 `--common-matches` 时，compare_models.py 执行传统对比

4. **性能考虑**：
   - 保存详细匹配会略微增加评测时间（约5-10%）
   - 主要开销在JSON序列化

## 常见问题

### Q1: 为什么Common Matches不是100%？

A: 有以下几种可能：
- 模型的召回率不同
- IoU阈值导致的边界情况
- 2D检测质量差异

### Q2: 独有匹配有什么特点？

A: 可以使用以下分析：
```bash
# find_common_matches.py 会输出Per-Class统计
python eval_tools/find_common_matches.py ... 
```

查看输出中的 "Model X Unique" 数量和比例。

### Q3: 如何可视化独有匹配？

A: 可以基于 detailed_3d_matches.json 找出独有匹配的case和frame，然后可视化：

```python
# 找出 model2 独有的匹配
for case in model2_matches:
    for frame in model2_matches[case]:
        for cls in model2_matches[case][frame]:
            for match in model2_matches[case][frame][cls]:
                gt_id = match['gt_id']
                if gt_id not in common_gt_ids:
                    # 这是 model2 独有的匹配
                    visualize(case, frame, match)
```

## 总结

使用共同匹配对比方案：
- ✅ 公平对比：确保比较相同目标的预测质量
- ✅ 问题诊断：识别哪些目标一个模型能匹配而另一个不能
- ✅ 性能分析：可以单独分析各模型独有匹配的特点
- ✅ 向后兼容：不影响现有评测流程

## 相关文档

- [COMMON_MATCH_COMPARISON_DESIGN.md](COMMON_MATCH_COMPARISON_DESIGN.md) - 详细设计方案
- [eval_tools/find_common_matches.py](find_common_matches.py) - 共同匹配查找工具
- [eval_tools/compare_models.py](compare_models.py) - 模型比较工具
