计算bbox的mAP的代码

import numpy as np
from sklearn.utils.linear_assignment_ import linear_assignment


def iou(bb_test, bb_gt):
    '''
    Computes IOU between two bboxes in the form [x1,y1,x2,y2]
    Parameters:
        bb_test: [x1,y1,x2,y2,...]
        bb_ground: [x1,y1,x2,y2,...]
    Returns:
        score: float, takes values between 0 and 1.
        score = Area(bb_test intersects bb_gt)/Area(bb_test unions bb_gt)
    '''
    xx1 = max(bb_test[0], bb_gt[0])
    yy1 = max(bb_test[1], bb_gt[1])
    xx2 = min(bb_test[2], bb_gt[2])
    yy2 = min(bb_test[3], bb_gt[3])
    w = max(0., xx2 - xx1)
    h = max(0., yy2 - yy1)
    area = w * h
    score = area / ((bb_test[2] - bb_test[0]) * (bb_test[3] - bb_test[1])
                    + (bb_gt[2] - bb_gt[0]) * (bb_gt[3] - bb_gt[1]) - area)
    return score


iou_thresh = 0.6
def assign(predict_boxes, real_boxes):
    iou_metric = []
    for box in predict_boxes:
        temp_iou = []
        for box2 in real_boxes:
            temp_iou.append(iou(box, box2))
        iou_metric.append(temp_iou)
    iou_metric = np.array(iou_metric)
    result = linear_assignment(-iou_metric)
    output = []
    output_iou = []
    for idx in range(len(result)):
        if iou_metric[result[idx][0],result[idx][1]] > iou_thresh:
            output.append(result[idx])
            output_iou.append(iou_metric[result[idx][0],result[idx][1]])
    return output, output_iou


#       predict
#     yes    no
# yes  TP    FN    real
# no   FP    TN

# acc = (TP + TN)/(TP+FN+FP+TN)
# recall = TP/(TP + FN)
#
# 调节score阈值,算出召回率从0到1时的准确率,得到一条曲线
# 计算曲线的下面积 则为AP


def get_auc(xy_arr):
    # 计算曲线下面积即AUC
    auc = 0.
    prev_x = 0
    for x, y in xy_arr:
        if x != prev_x:
            auc += (x - prev_x) * y
            prev_x = x
    x = [_v[0] for _v in xy_arr]
    y = [_v[1] for _v in xy_arr]
    # 画出auc图
    # plt.ylabel("False Positive Rate")
    # plt.plot(x, y)
    # plt.show()
    # print(xy_arr)
    return auc

def caculate_AP(predict_boxes, real_boxes):
    recall_arr = []
    acc_arr = []
    xy_arr = []
    score_arr = list(map(lambda input:float(input)*0.01, range(0, 101)))
    for score in score_arr:
        temp_predict_boxes = []
        for box in predict_boxes:
            if box[4]>score:
                temp_predict_boxes.append(box)
        result,_ = assign(temp_predict_boxes, real_boxes)
        TP = len(result)
        FN = len(real_boxes) - TP
        FP = len(temp_predict_boxes) - TP
        recall = TP/(TP+FN)
        acc = TP/(TP+FN+FP)
        recall_arr.append(recall)
        acc_arr.append(acc)
        xy_arr.append([recall,acc])
    return get_auc(xy_arr)


def get_mAP(all_predict_boxes, all_real_boxes):
    ap_arr = []
    for idx in range(len(all_predict_boxes)):
        ap_arr.append(caculate_AP(all_predict_boxes[idx], all_real_boxes[idx]))
    return np.mean(ap_arr)


if __name__ == '__main__':
    print(get_mAP(np.random.uniform(0, 1, (100, 10, 5)), np.random.uniform(0, 1, (100, 10, 4))))

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 YOLOv5 中,使用的是 mAP(mean Average Precision)指标来衡量模型的性能。计算 mAP代码如下: ```python from utils.general import plot_results, check_file def test(cfg, data, batch_size=16, img_size=640, iou_thres=0.65, conf_thres=0.25, save_json=False, single_cls=False, augment=False, verbose=False, model=None): # 加载模型 model = model.to(device).eval() # 加载数据集 dataloader = create_dataloader(data, img_size=img_size, batch_size=batch_size, stride=int(cfg.stride), pad=cfg.pad, rect=cfg.rect, augment=augment, cache=cfg.cache_images, single_cls=single_cls, pad_method=cfg.pad_method, hyp=hyp, rank=rank, world_size=world_size) # 初始化变量 seen = 0 pred = [] tbar = tqdm(dataloader, desc=f'Caching images') for i, (imgs, targets, paths, shapes) in enumerate(tbar): # 将数据传输到 GPU 上 imgs = imgs.to(device, non_blocking=True) # 前向传播 with torch.no_grad(): outputs = model(imgs) # 后处理 outputs = non_max_suppression(outputs, conf_thres=conf_thres, iou_thres=iou_thres, multi_label=False) # 更新变量 seen += imgs.shape[0] # 处理预测结果 for si, pred_i in enumerate(outputs): # 如果没有预测结果,则跳过 if pred_i is None: continue # 反归一化预测框坐标 pred_i[:, :4] = scale_coords(imgs.shape[2:], pred_i[:, :4], shapes[si]).round() # 将预测结果转换为 COCO 格式 for xi, x in enumerate(pred_i): # 如果没有预测结果,则跳过 if x is None: continue # 将预测结果转换为 COCO 格式 box = x[:4].tolist() score = float(x[4]) label = int(x[5]) image_id = int(Path(paths[si]).stem.split('_')[-1]) pred.append({'image_id': image_id, 'category_id': label, 'bbox': [round(float(x), 3) for x in box], 'score': round(score, 5)}) # 保存预测结果 if save_json and rank in [-1, 0]: pred_path = 'predictions.json' with open(pred_path, 'w') as file: json.dump(pred, file) # 计算 mAP if rank in [-1, 0]: # 如果是多进程,则需要将预测结果合并 if world_size > 1: pred = comm.gather(pred, dst=0) if rank == 0: pred = list(itertools.chain(*pred)) # 计算 mAP with open(data) as f: data_dict = yaml.load(f, Loader=yaml.SafeLoader) # config dict names = ['data/coco.names'] nc = 80 if single_cls: nc = 1 names = ['data/single.names'] if len(pred): # 将预测结果转换为 COCO 格式 pred = {x['image_id']: pred_i for x in pred for pred_i in x['instances']} gt = json.load(open(data_dict['val'].get('ann').rstrip('.json') + '_instances.json', 'r')) # 计算 AP ap, p, r, f1, ap_class = ap_per_class(pred, gt, iou_thres=iou_thres, conf_thres=conf_thres, use_07_metric=False) # 输出 mAP mp, mr, map50, map = np.mean(p), np.mean(r), ap_class[0], np.mean(ap) nt = np.bincount(gt['labels'], minlength=nc) if np.bincount(ap_class) > 1: print(f"mAP{'@[IoU=0.50:0.95]' * (iou_thres > 0.5)}: {map * 100:.2f}%") print(f"mAP{'@[IoU=0.50]' * (iou_thres > 0.5)}: {map50 * 100:.2f}%") print(f"mAP{'@[IoU=0.75]' * (iou_thres > 0.75)}: {ap_class.mean() * 100:.2f}%") print(f"mAP{'@[IoU=0.50:0.95]' * (iou_thres > 0.5)}, medium: {np.median(ap) * 100:.2f}%") print(f"Recall: {mr * 100:.2f}%") print(f"Precision: {mp * 100:.2f}%") print(f"F1-score: {f1.mean() * 100:.2f}%") print(f"Unique classes detected: {len(ap_class)}") else: print('No detections found by YOLOv5, mAP cannot be calculated.') ``` 其中,`ap_per_class()` 函数用于计算每个类别的 AP 值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值