You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改代码,基于含xmin/ymin/xmax/ymax的数据集计算Precision与Recall

目标检测场景下的Precision与Recall计算方案

你的问题本质是目标检测任务中的指标计算,和原代码针对的二分类任务逻辑完全不同,原代码无法直接修改适配,需要基于 bounding box 的匹配规则重新实现。以下是可行思路和代码实现:

核心逻辑说明

目标检测中Precision和Recall的计算依赖:

  • 用**IoU(交并比)**判断预测框与真实框是否匹配(通常IoU阈值设为0.5,可调整)
  • 统计TP(正确匹配的预测框)、FP(无对应真实框的预测框)、FN(无对应预测框的真实框)
  • 公式:
    • 精确率(Precision) = TP / (TP + FP)
    • 召回率(Recall) = TP / (TP + FN)
  • 若要绘制Precision-Recall曲线,需按预测框的置信度排序,依次计算不同置信度阈值下的P和R

具体代码实现

1. 基础工具函数(计算IoU)

def calculate_iou(box1, box2):
    # box格式:[xmin, ymin, xmax, ymax]
    x1_min, y1_min, x1_max, y1_max = box1
    x2_min, y2_min, x2_max, y2_max = box2
    
    # 计算交集坐标
    inter_xmin = max(x1_min, x2_min)
    inter_ymin = max(y1_min, y2_min)
    inter_xmax = min(x1_max, x2_max)
    inter_ymax = min(y1_max, y2_max)
    
    # 计算交集面积
    inter_width = max(0, inter_xmax - inter_xmin)
    inter_height = max(0, inter_ymax - inter_ymin)
    inter_area = inter_width * inter_height
    
    # 计算两个框的面积
    box1_area = (x1_max - x1_min) * (y1_max - y1_min)
    box2_area = (x2_max - x2_min) * (y2_max - y2_min)
    
    # 计算IoU
    iou = inter_area / (box1_area + box2_area - inter_area)
    return iou

2. 匹配真实框与预测框并统计指标

假设你的数据格式:

  • ground_truth_boxes:真实框列表,每个元素是[xmin, ymin, xmax, ymax]
  • predicted_boxes:预测框列表,每个元素是[xmin, ymin, xmax, ymax, confidence](需包含置信度用于排序)
import numpy as np
import matplotlib.pyplot as plt

def compute_precision_recall(gt_boxes, pred_boxes, iou_threshold=0.5):
    # 按置信度从高到低排序预测框
    pred_boxes_sorted = sorted(pred_boxes, key=lambda x: x[4], reverse=True)
    
    # 标记真实框是否已被匹配
    gt_matched = [False] * len(gt_boxes)
    tp = 0
    fp = 0
    
    # 遍历每个预测框
    for pred_box in pred_boxes_sorted:
        pred_box_coords = pred_box[:4]
        best_iou = 0
        best_gt_idx = -1
        
        # 找当前预测框匹配的最佳真实框
        for idx, gt_box in enumerate(gt_boxes):
            if not gt_matched[idx]:
                iou = calculate_iou(pred_box_coords, gt_box)
                if iou > best_iou and iou >= iou_threshold:
                    best_iou = iou
                    best_gt_idx = idx
        
        if best_gt_idx != -1:
            # 匹配成功,TP加1,标记真实框为已匹配
            tp += 1
            gt_matched[best_gt_idx] = True
        else:
            # 无匹配真实框,FP加1
            fp += 1
    
    # FN是未被匹配的真实框数量
    fn = sum(not matched for matched in gt_matched)
    
    # 计算Precision和Recall(避免除以0)
    precision = tp / (tp + fp) if (tp + fp) > 0 else 0.0
    recall = tp / (tp + fn) if (tp + fn) > 0 else 0.0
    
    return precision, recall, tp, fp, fn

3. 绘制Precision-Recall曲线

如果需要绘制PR曲线,需遍历不同置信度阈值,计算每个阈值下的P和R:

def plot_pr_curve(gt_boxes, pred_boxes, iou_threshold=0.5):
    # 按置信度排序预测框
    pred_boxes_sorted = sorted(pred_boxes, key=lambda x: x[4], reverse=True)
    confidences = [box[4] for box in pred_boxes_sorted]
    
    # 生成不同的置信度阈值(取所有预测框的置信度作为候选阈值)
    thresholds = np.unique(confidences)[::-1]
    precisions = []
    recalls = []
    
    for threshold in thresholds:
        # 筛选置信度>=当前阈值的预测框
        filtered_preds = [box for box in pred_boxes_sorted if box[4] >= threshold]
        p, r, _, _, _ = compute_precision_recall(gt_boxes, filtered_preds, iou_threshold)
        precisions.append(p)
        recalls.append(r)
    
    # 添加(0,1)点让曲线更完整
    precisions.append(1.0)
    recalls.append(0.0)
    
    # 绘制曲线
    plt.figure(figsize=(8, 6))
    plt.plot(recalls, precisions, color='purple', linewidth=2)
    plt.title('Precision-Recall Curve (IoU Threshold={})'.format(iou_threshold))
    plt.xlabel('Recall')
    plt.ylabel('Precision')
    plt.xlim([0.0, 1.0])
    plt.ylim([0.0, 1.05])
    plt.grid(True)
    plt.show()

4. 测试示例

# 模拟数据
ground_truth = [
    [10, 20, 50, 60],
    [30, 40, 70, 80],
    [60, 10, 90, 30]
]

predicted = [
    [12, 22, 48, 58, 0.95],  # 匹配第一个真实框
    [32, 42, 68, 78, 0.9],   # 匹配第二个真实框
    [55, 15, 85, 25, 0.8],   # 匹配第三个真实框
    [100, 100, 120, 120, 0.7], # 无匹配,FP
    [25, 35, 65, 75, 0.6]    # 第二个真实框已被匹配,FP
]

# 计算单阈值下的指标
precision, recall, tp, fp, fn = compute_precision_recall(ground_truth, predicted)
print(f"Precision: {precision:.2f}, Recall: {recall:.2f}")
print(f"TP: {tp}, FP: {fp}, FN: {fn}")

# 绘制PR曲线
plot_pr_curve(ground_truth, predicted)

关键注意事项

  • IoU阈值是可调参数,常见取值0.5,也可根据任务需求调整(如0.75)
  • 若你的预测框没有置信度,可根据框的质量(如模型输出的分类分数)生成,或仅计算单阈值下的P和R
  • 若存在多类别目标,需按类别分别计算指标后再求平均(如mAP)

内容的提问来源于stack exchange,提问作者user19438162

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 12:09:20