按照yolov5中计算precision和recall的方式,计算最大f1分数时的iou下的p和r
需要修改两个地方:
1、yolox/evaluators/voc_eval.py
在最后几行,计算最大f1分数时的iou下的p和r,并且返回值
# compute precision recall
fp = np.cumsum(fp)
tp = np.cumsum(tp)
rec = tp / float(npos)
# avoid divide by zero in case the first detection matches a difficult
# ground truth
prec = tp / np.maximum(tp + fp, np.finfo(np.float64).eps)
ap = voc_ap(rec, prec, use_07_metric)
#计算最大f1分数时,对应iou的p和r
f1 = 2 * prec * rec / (prec + rec + 1e-16)
i = f1.argmax()
f1_best = f1[i]
rec_best = rec[i]
prec_best = prec[i]
return rec, prec, ap, f1_best, rec_best, prec_best
2、yolox/data/datasets/voc.py
将第一步的返回值输出打印就行了。输出每个类别的P、R以及AP,和所有类别的P、R、mAP。想输出别的指标比如f1、acc等,同理。
def _do_python_eval(self, output_dir="output", iou=0.5):
rootpath = os.path.join(self.root, "VOC" + self._year)
name = self.image_set[0][1]
annopath = os.path.join(rootpath, "Annotations", "{:s}.xml")
imagesetfile = os.path.join(rootpath, "ImageSets", "Main", name + ".txt")
cachedir = os.path.join(
self.root, "annotations_cache", "VOC" + self._year, name
)
if not os.path.exists(cachedir):
os.makedirs(cachedir)
aps = []
recs = []
precs = []
# The PASCAL VOC metric changed in 2010
use_07_metric = True if int(self._year) < 2010 else False
print("Eval IoU : {:.2f}".format(iou))
if output_dir is not None and not os.path.isdir(output_dir):
os.mkdir(output_dir)
for i, cls in enumerate(VOC_CLASSES):
if cls == "__background__":
continue
filename = self._get_voc_results_file_template().format(cls)
rec, prec, ap, f1_best, rec_best, prec_best = voc_eval(
filename,
annopath,
imagesetfile,
cls,
cachedir,
ovthresh=iou,
use_07_metric=use_07_metric,
)
aps += [ap]
recs += [rec_best]
precs += [prec_best]
if iou == 0.5:
print("--------------------------------------------------------------")
print("AP for {} = {:.4f}".format(cls, ap))
print("Recall for {}= {:.4f}".format(cls, rec_best))
print("Precision for {} = {:.4f}".format(cls, prec_best))
if output_dir is not None:
with open(os.path.join(output_dir, cls + "_pr.pkl"), "wb") as f:
pickle.dump({"rec": rec, "prec": prec, "ap": ap}, f)
if iou == 0.5:
print("--------------------------------------------------------------")
print("Mean AP = {:.4f}".format(np.mean(aps)))
print("Mean Recall = {:.4f}".format(np.mean(recs)))
print("Mean Precision = {:.4f}".format(np.mean(precs)))
# print("~~~~~~~~")
# print("Results:")
# for ap in aps:
# print("{:.3f}".format(ap))
# print("{:.3f}".format(np.mean(aps)))
# print("~~~~~~~~")
print("")
print("--------------------------------------------------------------")
print("Results computed with the **unofficial** Python eval code.")
print("Results should be very close to the official MATLAB eval code.")
print("Recompute with `./tools/reval.py --matlab ...` for your paper.")
print("-- Thanks, The Management")
print("--------------------------------------------------------------")
return np.mean(aps)
PS:我是按照yolov5输出precision和recall的计算方法改的,方便和yolov5做对比。如有不正确请各位大佬指正。