假设当前经过标签数据与预测数据的加载,我们得到了下面两个变量:
- det_boxes:包含全部图像中所有类别的预测框,其中一个边框包含了[left, top, right, bottom, score, NameofImage]
- gt_boxes:包含了全部图像中所有类别的标签,其中一个标签的内容为[left, top, right, bottom, 0]。需要注意的是,最后一位0代表该标签有没有被匹配过,如果匹配过则会置1,其他预测框再去匹配则为误检框。
下面是所有类别的评测过程。
for c in classes:# 通过类别作为关键字,得到每个类别的预测、标签及总标签数dects = det_boxes[c]gt_class = gt_boxes[c]npos = num_pos[c]#利用得分作为关键字,对预测框按照得分从高到低排序dects = sorted(dects, key = lambda conf: conf[5], reverse = True)#设置两个与预测边框长度相同的列表,标记是True Positive还是False PositiveTP = np.zeros(len(dects))FP = np.zeros(len(dects))#对某一个类别的预测框进行遍历for d in range(len(dets)):#将iou默认置为最低iouMax = sys.float_info.min#遍历与预测框同一图像中的同一类别的标签,计算iouif dects[d][-1] in gt_class:for j in range(len(gt_class[dects[d][-1]])):iou = Evaluator.iou(dects[d][:4], gt_class[dects[d][-1]][j][:4])if iou > iouMax:iouMax = ioujmax = j #记录与预测有最大iou的标签#如果最大iou大于阈值,并且没有被匹配过,则赋予TPif iouMax >= cfg['iouThreshold']:if gt_class[dects[d][-1]][jmax][4] == 0:TP[d] = 1gt_class[dects[d][-1]][jmax][4] = 1 #标记为匹配过#如果被匹配过,赋予FPelse:FP[d] = 1#如果最大iou没有超过阈值,赋予FPelse;FP[d] = 1#如果对应图像中没有该类别的标签,赋予FPelse:FP[d] = 1#利用NumPy的cumsum()函数,计算累计的FP与TPacc_FP = np.cumsum(FP)acc_TP = np.cumsum(TP)rec = acc_TP / npos #得到每个点的Recallprec = np.divide(acc_TP, (acc_FP + acc_TP)) #得到每个点的Precision#利用Recall与Precision进一步计算得到AP[ap, mpre, mrec, ii] = Evaluator.CalculateAveragePrecision(rec, prec)