目标检测中的评价指标计算

发布于:2025-07-11 ⋅ 阅读:(20) ⋅ 点赞:(0)

在目标检测(Object Detection)任务中,统计 TP、TN、FP、FN 的逻辑比普通分类更复杂,因为需要同时考虑位置准确性类别预测。以下是详细说明:

一、检测任务中的核心概念

  1. 真实框(Ground Truth, GT):标注的真实目标位置和类别。
  2. 预测框(Prediction):模型输出的目标位置和类别。
  3. IoU(Intersection over Union):衡量预测框与真实框的重叠程度,计算公式为:
    IoU=预测框与真实框的并集面积预测框与真实框的交集面积​
    • 通常设定一个阈值(如 IoU ≥ 0.5)作为 “预测正确” 的标准。

二、TP、FP、FN 的统计规则

对于每个预测框和真实框,按以下规则统计:

1. TP(True Positive)
  • 条件:
    1. 预测框与某个真实框的 IoU ≥ 阈值(如 0.5)。
    2. 预测的类别与该真实框的类别一致。
    3. 该真实框尚未被其他预测框匹配(避免多个预测框重复匹配同一真实框)。
2. FP(False Positive)
  • 条件:
    1. 预测框与所有真实框的 IoU <阈值(即预测了一个不存在的目标,“误检”)。
    2. 或预测框与某个真实框的 IoU ≥ 阈值,但类别预测错误(“类别错误”)。
3. FN(False Negative)
  • 条件:
    真实框没有被任何预测框以足够高的 IoU 匹配(即模型 “漏检” 了该目标)。
4. TN(True Negative)
  • 在目标检测中,TN 通常不直接统计,因为检测任务主要关注 “是否检测到目标”,而非背景区域。
    • 若需严格定义:所有背景区域(无真实目标)被正确预测为无目标的情况。

三、统计步骤(算法流程)

  1. 按置信度排序预测框
    模型输出的预测框通常带有置信度分数(如 0.9, 0.85 等),需按分数从高到低排序。

  2. 遍历每个预测框

    • 对当前预测框,找到与其 IoU 最高的真实框。
    • 判断是否满足 TP 条件(IoU ≥ 阈值且类别一致)。
    • 若满足,标记该真实框为 “已匹配”,当前预测框记为 TP。
    • 若不满足,当前预测框记为 FP。
  3. 统计 FN
    所有未被匹配的真实框记为 FN。

  4. 代码例子

  5. import numpy as np
    
    def calculate_iou(box1, box2):
        """计算两个边界框的 IoU"""
        # box 格式:[x1, y1, x2, y2](左上角和右下角坐标)
        x1 = max(box1[0], box2[0])
        y1 = max(box1[1], box2[1])
        x2 = min(box1[2], box2[2])
        y2 = min(box1[3], box2[3])
        
        # 计算交集面积
        intersection = max(0, x2 - x1) * max(0, y2 - y1)
        
        # 计算并集面积
        area1 = (box1[2] - box1[0]) * (box1[3] - box1[1])
        area2 = (box2[2] - box2[0]) * (box2[3] - box2[1])
        union = area1 + area2 - intersection
        
        # 避免除零错误
        if union == 0:
            return 0
        
        return intersection / union
    
    def evaluate_detections(gt_boxes, pred_boxes, iou_threshold=0.5):
        """评估检测结果,统计 TP、FP、FN"""
        # 按置信度降序排序预测框
        if len(pred_boxes) > 0:
            pred_boxes = sorted(pred_boxes, key=lambda x: x[4], reverse=True)
        
        # 标记真实框是否已被匹配
        gt_matched = [False] * len(gt_boxes)
        
        # 初始化 TP、FP 计数器
        tp = 0
        fp = 0
        
        # 遍历每个预测框
        for pred in pred_boxes:
            pred_box = pred[:4]  # 边界框坐标
            pred_class = pred[5]  # 预测类别
            
            best_iou = 0
            best_gt_idx = -1
            
            # 找到与当前预测框 IoU 最高的真实框
            for i, gt in enumerate(gt_boxes):
                gt_box = gt[:4]
                gt_class = gt[4]
                
                # 仅考虑同一类别的真实框
                if pred_class == gt_class:
                    iou = calculate_iou(pred_box, gt_box)
                    if iou > best_iou:
                        best_iou = iou
                        best_gt_idx = i
            
            # 判断是否为 TP
            if best_iou >= iou_threshold and best_gt_idx != -1 and not gt_matched[best_gt_idx]:
                tp += 1
                gt_matched[best_gt_idx] = True  # 标记该真实框已被匹配
            else:
                fp += 1
        
        # 统计 FN:未被匹配的真实框数量
        fn = sum(not matched for matched in gt_matched)
        
        return tp, fp, fn
    
    # 示例数据
    gt_boxes = [
        [10, 10, 50, 50, 1],  # [x1, y1, x2, y2, 类别]
        [100, 100, 150, 150, 2]
    ]
    
    pred_boxes = [
        [12, 12, 52, 52, 0.9, 1],  # [x1, y1, x2, y2, 置信度, 类别]
        [90, 90, 140, 140, 0.8, 2],
        [200, 200, 250, 250, 0.7, 1]  # 误检
    ]
    
    tp, fp, fn = evaluate_detections(gt_boxes, pred_boxes, iou_threshold=0.5)
    print(f"TP = {tp}, FP = {fp}, FN = {fn}")

    五、注意事项

  6. IoU 阈值选择

    • 常用阈值为 0.5(COCO 数据集使用 0.5:0.95 的多个阈值)。
    • 阈值越高,对位置准确性的要求越严格。
  7. 多类别处理

    • 需对每个类别单独统计 TP、FP、FN,再汇总结果。
  8. 平均精度(mAP)

    • 在实际评估中,通常使用 mAP(Mean Average Precision)作为综合指标,它考虑了不同 IoU 阈值和召回率下的精度。
  9. 工具库

    • 推荐使用 pycocotools 或 torchmetrics 等成熟库进行评估,避免手动实现复杂逻辑。

内容来自豆包


网站公告

今日签到

点亮在社区的每一天
去签到