博主在这一个问题上犯了两个错,本文提供的方法不仅仅适用于SSD的eval.py
同样适用于解决其他项目中的voc_eval.py。
博主思考查询了一晚上,若对你有帮助,给个赞!!!
def voc_eval(detpath,
annopath,
imagesetfile,
classname,
cachedir,
ovthresh=0.5,
use_07_metric=False):
if not os.path.isdir(cachedir):
os.mkdir(cachedir)
cachefile = os.path.join(cachedir, 'annots.pkl')
# read list of images
with open(imagesetfile, 'r') as f:
lines = f.readlines()
imagenames = [x.strip() for x in lines]
# print(imagenames)
if not os.path.isfile(cachefile):
# load annots
recs = {}
for i, imagename in enumerate(imagenames):
recs[imagename] = parse_rec(annopath % (imagename))
if i % 100 == 0:
print('Reading annotation for {:d}/{:d}'.format(
i + 1, len(imagenames)))
# save
print('Saving cached annotations to {:s}'.format(cachefile))
with open(cachefile, 'wb') as f:
pickle.dump(recs, f)
else:
# load
with open(cachefile, 'rb') as f:
recs = pickle.load(f)
# extract gt objects for this class
class_recs = {}
npos = 0
for imagename in imagenames:
# print(imagename)
# for obj in recs[imagename]:
# if obj['name'] == classname:
# print('obj[name]:', obj['name'], classname)
R = [obj for obj in recs[imagename] if obj['name'] == classname]
# print('R', len(R))
# for obj in recs[imagename]:
# print('classname:', classname, 'obj[name]:', obj['name'])
bbox = np.array([x['bbox'] for x in R])
# difficult = np.array([x['difficult'] for x in R]).astype(np.bool)
difficult = np.zeros(len(R)).astype(np.bool)
det = [False] * len(R)
# npos = npos + sum(~difficult) # 没有difficult 则nops就为gt
npos = npos + len(R) # len(R) gt ground truth的数量
class_recs[imagename] = {'bbox': bbox,
'difficult': difficult,
'det': det}
print('npos', npos)
# read dets
detfile = detpath.format(classname)
# print(detfile)
with open(detfile, 'r') as f:
lines = f.readlines()
if any(lines) == 1:
splitlines = [x.strip().split(' ') for x in lines]
image_ids = [x[0] for x in splitlines]
confidence = np.array([float(x[1]) for x in splitlines])
BB = np.array([[float(z) for z in x[2:]] for x in splitlines])
# sort by confidence
sorted_ind = np.argsort(-confidence)
sorted_scores = np.sort(-confidence)
BB = BB[sorted_ind, :]
image_ids = [image_ids[x] for x in sorted_ind]
# go down dets and mark TPs and FPs
nd = len(image_ids)
tp = np.zeros(nd)
fp = np.zeros(nd)
for d in range(nd):
R = class_recs[image_ids[d]]
bb = BB[d, :].astype(float)
ovmax = -np.inf
BBGT = R['bbox'].astype(float)
if BBGT.size > 0:
# compute overlaps
# intersection
ixmin = np.maximum(BBGT[:, 0], bb[0])
iymin = np.maximum(BBGT[:, 1], bb[1])
ixmax = np.minimum(BBGT[:, 2], bb[2])
iymax = np.minimum(BBGT[:, 3], bb[3])
iw = np.maximum(ixmax - ixmin, 0.)
ih = np.maximum(iymax - iymin, 0.)
inters = iw * ih
uni = ((bb[2] - bb[0]) * (bb[3] - bb[1]) +
(BBGT[:, 2] - BBGT[:, 0]) *
(BBGT[:, 3] - BBGT[:, 1]) - inters)
overlaps = inters / uni
ovmax = np.max(overlaps)
jmax = np.argmax(overlaps)
if ovmax > ovthresh:
if not R['difficult'][jmax]:
if not R['det'][jmax]:
tp[d] = 1.
R['det'][jmax] = 1
else:
fp[d] = 1.
# fp[d] = 1.
else:
fp[d] = 1.
# compute precision recall
fp = np.cumsum(fp)
tp = np.cumsum(tp)
rec = tp / float(npos)
print(fp, tp, rec)
# 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)
else:
rec = -1.
prec = -1.
ap = -1.
return rec, prec, ap
if not R['difficult'][jmax]:
if not R['det'][jmax]:
tp[d] = 1.
R['det'][jmax] = 1
else:
fp[d] = 1.`
报错,因此需要做出如下更改,因为无difficult,意味着difficult全为0,difficult = np.zeros(len®).astype(np.bool)用其替换就可以了,然后将原来的npos=npos+sum(~difficult)这句可以修改也可以不改,改的话可以直接用len®代替sum部分,因为len®就是gt目标数量。如此基本上就不会出现MAP为0的情况了。
yolo可视化——loss、Avg IOU、P-R、mAP、Recall (没有xml文件的情况)
Faster R-CNN/R-FCN里mAP的计算过程(voc_eval.py解析)