supervision Legacy 评估 API 详解:ConfusionMatrix 与 MeanAveragePrecision 的原理、用法与迁移指南
【免费下载链接】supervisionWe write your reusable computer vision tools. 💜项目地址: https://gitcode.com/GitHub_Trending/su/supervision
本篇聚焦 supervision 文档中的 Legacy Metrics(遗留评估 API),即 src/supervision/metrics/detection.py 中实现的ConfusionMatrix与MeanAveragePrecision两个对象检测评估类。文章覆盖二者的完整属性、构建方式、贪心匹配与 COCO 101 点插值等底层实现细节,以及自0.23.0起引入的新 metrics 模块与遗留 API 的关系和迁移路径。读完后可独立完成:安装 metrics 依赖、用from_detections/from_tensors/benchmark三种入口计算混淆矩阵与 mAP,理解 TP/FP/FN 归属逻辑,并判断何时应改用新版指标模块。
Legacy Metrics 的定位与安装
自 supervision0.23.0起,项目引入了全新的 metrics 模块(src/supervision/metrics/init.py 导出的MeanAveragePrecision、F1Score、Precision、Recall、MeanAverageRecall等)。sv.ConfusionMatrix和顶层sv.MeanAveragePrecision(来自supervision.metrics.detection)则属于遗留评估 API,文档明确说明其"will be deprecated in the future"(见 docs/detection/metrics.md)。
使用本页 API 前,需要安装 metrics 可选依赖:
pip install "supervision[metrics]"从 pyproject.toml 可以看到,该 extra 目前只额外安装了pandas>=2。这两个类通过 src/supervision/init.py 暴露在顶层命名空间,因此可直接以sv.ConfusionMatrix、sv.MeanAveragePrecision的方式引用。
需要注意两者的废弃状态并不相同(以当前仓库源码为准,当前开发版本为0.31.0.dev0):
| 类 | 废弃标记(源码事实) |
|---|---|
sv.ConfusionMatrix | 未加@deprecated_class装饰器,但被文档归为 legacy API |
sv.MeanAveragePrecision | 有@deprecated_class(deprecated_in="0.27.0", remove_in="0.31.0"),且 docstring 明确提示其结果与 pycocotools 不一致,推荐使用supervision.metrics.mean_average_precision.MeanAveragePrecision |
ConfusionMatrix:按类统计 TP / FP / FN
ConfusionMatrix是一个 dataclass,定义于 src/supervision/metrics/detection.py,用于对象检测任务的混淆矩阵统计。其核心属性如下:
| 属性 | 类型 | 说明 |
|---|---|---|
matrix | np.ndarray[np.int32] | 形状为(len(classes) + 1, len(classes) + 1)的二维矩阵,最后多出的行列用于汇总 FP / FN |
classes | list[str] | 模型类别名列表 |
conf_threshold | float | 置信度阈值(0~1),低于该值的预测不计入矩阵 |
iou_threshold | float | IoU 阈值(0~1),低于该值的预测-真值对不会被匹配,预测记为 FP |
metric_target | MetricTarget | IoU 计算所用坐标类型:BOXES(默认)或ORIENTED_BOUNDING_BOXES;MASKS不受支持 |
MetricTarget枚举定义在 src/supervision/metrics/core.py,取值BOXES(xyxy 框)、MASKS(掩码)、ORIENTED_BOUNDING_BOXES(OBB 旋转框)。ConfusionMatrix仅支持前两者之外的 BOXES 与 OBB 两种——传入MetricTarget.MASKS会抛出ValueError(见detection.py中的_assert_supported_target)。
三种构建方式
1.from_detections:从sv.Detections列表构建
import numpy as np import supervision as sv targets = [ sv.Detections( xyxy=np.array([[0, 0, 10, 10], [50, 50, 60, 60]]), class_id=np.array([0, 0]), ) ] predictions = [ sv.Detections( xyxy=np.array([[0, 0, 10, 10], [100, 100, 110, 110]]), class_id=np.array([0, 0]), confidence=np.array([0.9, 0.8]), ) ] confusion_matrix = sv.ConfusionMatrix.from_detections( predictions=predictions, targets=targets, classes=["person"], conf_threshold=0.3, # 默认值 0.3 iou_threshold=0.5, # 默认值 0.5 ) print(confusion_matrix.matrix) # array([[1, 1], # [1, 0]], dtype=int32)from_detections内部先把每组Detections转换为张量再调用from_tensors。转换规则由detections_to_tensor实现(src/supervision/metrics/detection.py):
MetricTarget.BOXES:预测张量行格式(x_min, y_min, x_max, y_max, class_id, confidence),即(M, 6);真值无 confidence,为(N, 5)。MetricTarget.ORIENTED_BOUNDING_BOXES:要求detections.data[ORIENTED_BOX_COORDINATES]中存有 float32 的 OBB 坐标,形状(N, 8)(扁平)或(N, 4, 2)(sv.Detections.from_ultralytics的存储形式),内部统一规整为(N, 8);对应张量行为(x1, y1, x2, y2, x3, y3, x4, y4, class_id [, confidence]),即预测(M, 10)、真值(N, 9)。class_id为None会报错;with_confidence=True但confidence为None也会报错。
2.from_tensors:直接从 numpy 张量列表构建
import numpy as np import supervision as sv targets = [ np.array([ [0.0, 0.0, 3.0, 3.0, 0], [2.0, 2.0, 5.0, 5.0, 0], [6.0, 1.0, 8.0, 3.0, 1], ]) ] predictions = [ np.array([ [0.0, 0.0, 3.0, 3.0, 0, 0.9], [0.1, 0.1, 3.0, 3.0, 0, 0.9], [6.0, 1.0, 8.0, 3.0, 1, 0.8], ]) ] confusion_matrix = sv.ConfusionMatrix.from_tensors( predictions=predictions, targets=targets, classes=["person", "dog"], ) print(confusion_matrix.matrix) # array([[1, 0, 1], # [0, 1, 0], # [1, 0, 0]], dtype=int32)_validate_input_tensors会校验:预测与真值列表长度一致、元素必须是 numpy 数组、列数符合metric_target的期望(BOXES 为 6/5 列,OBB 为 10/9 列)。
3.benchmark:数据集 + 回调函数一步到位
import supervision as sv dataset = sv.DetectionDataset.from_yolo( images_directory_path=".../test/images", annotations_directory_path=".../test/labels", data_yaml_path=".../data.yaml", ) def callback(image: np.ndarray) -> sv.Detections: return model.predict(image[:, :, ::-1]) confusion_matrix = sv.ConfusionMatrix.benchmark( dataset=dataset, callback=callback, conf_threshold=0.3, iou_threshold=0.5, save_directory_path="./results", # 可选 ) print(confusion_matrix.matrix)benchmark遍历DetectionDataset(每轮产出image_name, image, annotation),调用callback得到预测后汇总。可选参数save_directory_path(关键参数,仅benchmark支持)会在该目录中为每张图写出一张 2x2 结果拼图,按原图文件名直接落盘:四个面板分别为Ground Truth、True Positives、False Positives、False Negatives。从源码看(_save_detection_validation_visualization,src/supervision/metrics/detection.py),该拼图通过_split_detections_by_outcome复用与evaluate_detection_batch相同的匹配逻辑划分 TP/FP/FN,并用BoxAnnotator/LabelAnnotator按类别着色绘制;若目录中已存在同名文件会发出UserWarning后覆盖。完整的基准测试工作流可参考 docs/how_to/benchmark_a_model.md。
匹配算法:TP / FP / FN 如何归属
单张图的矩阵累加由静态方法evaluate_detection_batch完成,流程可从源码逐段印证:
- 形状校验:预测
(M, 6)(或 OBB 下(M, 10)),真值(N, 5)(或(N, 9))。 - 置信度过滤:
predictions[confidence >= conf_threshold]留下参与匹配的预测。 - 边界短路:无有效预测时,所有真值计入
matrix[gt_class, num_classes](FN 汇总列);真值为空时,所有有效预测计入matrix[num_classes, det_class](FP 汇总行)。 - IoU 矩阵:BOXES 用
box_iou_batch,OBB 用oriented_box_iou_batch(均来自 src/supervision/detection/utils/iou_and_nms.py)。 - 贪心匹配:取所有
iou > iou_threshold的候选对,用np.lexsort按"同类优先、IoU 降序"排序后逐一贪心分配,每个真值与每个预测最多匹配一次。 - 跨类空间匹配的特殊处理:两个框空间重叠但类别不同时,
matrix[gt_class, det_class] += 1——即该预测对目标类别是 FP(错检),对预测类别是 FN(漏检),同一笔错检同时体现在两个位置。 - 汇总:未匹配真值累加到 FN 列,未匹配预测累加到 FP 行。
矩阵语义因此是:matrix[i, j](i != j且均在类索引范围内)= 真值为类 i 但被预测成类 j 的数量;对角线 = TP;最后一列 = 各类 FN;最后一行 = 各类 FP。
plot:热力图可视化
fig = confusion_matrix.plot( save_path=None, # 给路径则保存为 250 dpi 透明背景 PNG title="Corgi benchmark", # 可选标题 classes=None, # 自定义显示类别,None 则显示全部 normalize=False, # True 时按列归一化 fig_size=(12, 10), # 画布尺寸 )实现细节(plot方法):矩阵先转float64;normalize=True时按列求和归一化;小于0.005的单元格置为NaN以隐藏噪点;坐标轴刻度默认显示类名并追加FN/FP两个汇总刻度;格子数少于 30 个时会在每个单元格内标注数值,颜色随数值大小在黑/白之间切换。
MeanAveragePrecision(遗留版):mAP@50:95 的计算
sv.MeanAveragePrecision(frozen dataclass,定义于 src/supervision/metrics/detection.py)的四个属性为:
| 属性 | 含义 |
|---|---|
map50_95 | IoU 阈值 0.50~0.95(步长 0.05)十个档位上的 mAP 均值 |
map50 | 仅 IoU = 0.50 时的 mAP |
map75 | 仅 IoU = 0.75 时的 mAP |
per_class_ap50_95 | 每个类在 10 个 IoU 档位上的 AP 数组,形状(num_classes, 10) |
再次强调(源码 docstring 中的废弃提示):该实现自0.27.0起被标记 deprecated,计划于0.31.0移除;官方理由是"deprecated implementation provides results that are inconsistent with pycocotools",建议改用新版supervision.metrics.mean_average_precision.MeanAveragePrecision(该新实现与 pycocotools 结果一致)。如果你的目标是与 COCO 评测对齐,请优先走新模块;下述内容用于理解遗留实现本身及已有代码。
计算入口
import supervision as sv # 方式一:从 Detections 列表 mAP = sv.MeanAveragePrecision.from_detections( predictions=predictions_list, # list[sv.Detections] targets=targets_list, # list[sv.Detections] ) # 方式二:从张量列表(每图 (M,6) / (N,5)) mAP = sv.MeanAveragePrecision.from_tensors( predictions=prediction_tensors, targets=target_tensors, ) # 方式三:数据集 + 回调 mAP = sv.MeanAveragePrecision.benchmark( dataset=dataset, callback=callback, ) print(mAP.map50_95, mAP.map50, mAP.map75)一个最小示例:单图单框完全重合且类别一致时,map50为1.0;若真值为空的背景图上存在预测,这些预测全部计为 FP,会压低 AP(背景图语义在from_tensors的 docstring 中有明确说明)。
实现原理:IoU 档位、贪心匹配与 101 点插值
from_tensors的核心计算链可以从源码拆解为三步:
- 多档 IoU 匹配(
_match_detection_batch):IoU 档位为np.linspace(0.5, 0.95, 10),即[0.50, 0.55, ..., 0.95]共 10 档。对每一档,用box_iou_batch算整图 IoU 矩阵,要求iou >= 档位值且类别一致,再经_greedy_match(来自 src/supervision/metrics/utils/matching.py)保证每个真值与预测各只匹配一次。最终得到每图每档的 TP 布尔矩阵。 - 按置信度排序累计 P/R(
_average_precisions_per_class):所有图的匹配结果、预测置信度与类别被拼接后,按预测置信度全局降序排列;对每个类分别累加true_positives/false_positives,得到 recall 与 precision 曲线。注意此处只统计至少在一个真值图中出现的类——从未出现在 GT 中的类会被跳过。 - COCO 101 点插值(
compute_average_precision):将 precision 做从尾部起的最大值累积(单调包络),再在 recall = 0, 0.01, ..., 1.0 的 101 个取整点采样求均值,即标准 COCO AP 定义。
边界情况同样有源码背书:若所有图都没有真值,函数返回0.0而非NaN;map50/map75/map50_95分别取平均精度数组的第 1 列、第 6 列(0.75 档)与全体均值。
与新版指标的差异提示:新版supervision.metrics中的指标采用update(...).compute()的两段式 API(基类Metric定义于 src/supervision/metrics/core.py),支持MetricTarget.BOXES / MASKS / ORIENTED_BOUNDING_BOXES与AveragingMethod.MACRO / MICRO / WEIGHTED三种平均方式,并额外提供按对象尺寸(small / medium / large)的细分结果;而遗留版MeanAveragePrecision仅支持 xyxy 框、固定按类宏平均。
从 Legacy 迁移到新指标模块的对照
结合 src/supervision/metrics/init.py 的导出与 docs/metrics/ 下的文档,迁移对照关系如下:
| Legacy(本页) | 新模块推荐替代 | 关键差异 |
|---|---|---|
sv.MeanAveragePrecision(supervision.metrics.detection) | supervision.metrics.mean_average_precision.MeanAveragePrecision | 新版结果与 pycocotools 一致,支持 MASKS / OBB、尺寸细分 |
sv.ConfusionMatrix.from_detections(...) | 新模块未提供同名类,可保留使用 | 目前ConfusionMatrix源码中无废弃装饰器,但仍属 legacy 页面范畴,建议关注后续版本 |
一次性from_tensors | metric.update(predictions, targets).compute() | 新版支持流式累积,便于大图集分批评估 |
新模块各指标的详细说明可查阅仓库内文档:mAP、F1 Score、Precision、Recall、MAR、常用数值。
小结与适用前提
- 本仓库当前开发版本为
0.31.0.dev0(见 pyproject.toml),sv.MeanAveragePrecision携带"0.31.0 移除"的废弃标记,新增代码不应再依赖它;sv.ConfusionMatrix则暂无源码级废弃标记,但仍位于 legacy 文档页,使用时应留意版本演进。 - 使用任一 API 前先执行
pip install "supervision[metrics]";ConfusionMatrix要求预测携带confidence(benchmark/from_detections路径)、两者都要求class_id非空。 conf_threshold与iou_threshold默认值分别为0.3与0.5,直接决定 TP 判定口径,跨配置比较指标时必须保持一致。- 若需要逐图定位错检/漏检原因,
sv.ConfusionMatrix.benchmark(..., save_directory_path=...)会产出 GT/TP/FP/FN 四宫格拼图,是与数值指标配合的最快排障手段。
【免费下载链接】supervisionWe write your reusable computer vision tools. 💜项目地址: https://gitcode.com/GitHub_Trending/su/supervision
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考