In [ ]:
import json
from pprint import pprint
import matplotlib.pyplot as plt
folder = '../Questions/'
qfile = folder + '/MultipleChoice_mscoco_val2014_questions.json';
with open(qfile) as data_file:
qdata = json.load(data_file)
ofile = 'coco/annotations/instances_val2014.json';
with open(ofile) as data_file:
odata = json.load(data_file)
# dictionary mapping from category to name
cdata = odata['categories']
dict_cls_name = dict([(cdata[i]['id'],cdata[i]['name']) for i in range(len(cdata))])
dict_name_cls = dict([(cdata[i]['name'],cdata[i]['id']) for i in range(len(cdata))])
idata = odata['images']
adata = odata['annotations']
# dictionary mapping from image id to area
dict_img_area = {}
for i in range(len(idata)):
img = idata[i]['id']
w = idata[i]['width']
h = idata[i]['height']
assert(img not in dict_img_area)
dict_img_area[img] = w*h
# compute average instance area
a = 0.0
n = 0.0
ll = 0
for k in range(len(adata)):
img = adata[k]['image_id']
area = adata[k]['area']/dict_img_area[img]
if area < 0.05:
ll += 1
a += area
n += 1
a = a/n
ll = ll/n
print 'Instance level: area',a,'num',n,'fraction < 5%',ll
# dictionary mapping from (imageid, cls) to area
dict_imgcls_area = {}
for k in range(len(adata)):
img = adata[k]['image_id']
cls = adata[k]['category_id']
area = adata[k]['area']/dict_img_area[img]
if (img,cls) in dict_imgcls_area:
dict_imgcls_area[(img,cls)] += area
else:
dict_imgcls_area[(img,cls)] = area
# COMPUTE AVERAGE SIZE OF ALL CATEGORIES
a = 0.0
num_total = 0.0
for ic in dict_imgcls_area:
a += dict_imgcls_area[ic]
num_total += 1
area_avg = a/num_total
print 'Img+cat level: area',area_avg,'num',num_total
In [ ]:
# dictionary mapping from image id to list of words
dict_img_words = {}
for i in range(0,len(qdata['questions'])):
img = qdata['questions'][i]['image_id']
if img in dict_img_words:
d = dict_img_words[img]
else:
d = set()
q = qdata['questions'][i]['question']
w = q.split()
w = [ww.lower() for ww in w]
#if w[0] == 'is' and 'person' not in set(w):
# w = []
d = d.union(set(w))
dict_img_words[img] = d
# dictionary mapping from image id to set of detected classes
dict_img_detcls = {}
for img in dict_img_words:
words = dict_img_words[img]
detected = []
for w in words:
if w in dict_name_cls:
c = dict_name_cls[w]
detected += [c]
# can do something more complicated later
dict_img_detcls[img] = set(detected)
In [ ]:
import pickle
golden = pickle.load(open( 'coco_vectors/imgids_labels.p', "rb" ) )
for img in golden:
cls = golden[img]
if 897 in cls:
print img
#dict_img_detcls = golden
for img in dict_img_detcls:
dict_img_detcls[img] = dict_img_detcls[img].union(set(golden[img]))
In [ ]:
# COMPUTING AVERAGE SIZE OF DETECTED
ad = 0.0
nd = 0.0
au = 0.0
nu = 0.0
for ic in dict_imgcls_area:
img = ic[0]
cls = ic[1]
area = dict_imgcls_area[ic]
if cls in dict_img_detcls[img]:
ad += area
nd += 1
else:
au += area
nu += 1
ad = ad/nd
au = au/nu
print 'Detected: area',ad,'num',nd
print 'Undetected: area',au,'num',nu
# COMPUTE PER-CATEGORY AREA
dict_cls_area = {}
for ic in dict_imgcls_area:
cls = ic[1]
area = dict_imgcls_area[ic]
if cls in dict_cls_area:
dict_cls_area[cls] += [area]
else:
dict_cls_area[cls] = [area]
for c in dict_cls_area:
a = dict_cls_area[c]
dict_cls_area[c] = sum(a)/len(a)
# COMPUTING AVERAGE PER-CATEGORY AREA
a = dict_cls_area.values()
a = sum(a)/len(a)
print 'Per-category average area',a
# COMPUTING PER-CATEGORY RECALL
dict_cls_recall = {}
for ic in dict_imgcls_area:
img = ic[0]
cls = ic[1]
# this class is present in this image
bDetected = cls in dict_img_detcls[img]
# this class was maybe detected
if cls in dict_cls_recall:
dict_cls_recall[cls] += [bDetected]
else:
dict_cls_recall[cls] = [bDetected]
for c in dict_cls_recall:
r = dict_cls_recall[c]
dict_cls_recall[c] = float(sum(r))/len(r)
a = dict_cls_recall.values()
a = sum(a)/len(a)
print 'Per-category average recall',a
dict_cls_precision = {}
for img in dict_img_detcls:
detcls = dict_img_detcls[img] # detected classes
for c in detcls:
bCorrect = (img,c) in dict_imgcls_area # present in the image
if c in dict_cls_precision:
dict_cls_precision[c] += [bCorrect]
else:
dict_cls_precision[c] = [bCorrect]
for c in dict_cls_precision:
p = dict_cls_precision[c]
dict_cls_precision[c] = float(sum(p))/len(p)
avg_p = 0.0
for c in dict_cls_recall:
if c in dict_cls_precision:
avg_p += dict_cls_precision[c]
else:
print ' (Not detected',c,dict_cls_name[c],')'
avg_p += 1
a = avg_p/len(dict_cls_recall)
print 'Per-category average precision',a
In [ ]:
%matplotlib inline
fl = 16
ft = 13
classes = dict_cls_area.keys()
x = [dict_cls_area[c] for c in classes]
y = [dict_cls_recall[c] for c in classes]
ax1 = plt.subplot(1,2,1)
ax1.plot(x,y,'o')
ax1.set_xlim(0,0.35)
ax1.set_ylim(0,1)
ax1.set_xlabel('Object size',fontsize=fl)
ax1.set_ylabel('Recall',fontsize=fl)
plt.xticks([0, 0.1, 0.2, 0.3],fontsize=ft)
plt.yticks(fontsize=ft)
x = [dict_cls_area[c] for c in classes]
y = []
for c in classes:
if c in dict_cls_precision:
y += [dict_cls_precision[c]]
else:
y += [1]
ax2 = plt.subplot(1,2,2)
ax2.plot(x,y,'o')
ax2.set_xlim(0,0.35)
ax2.set_ylim(0,1)
ax2.set_xlabel('Object size',fontsize=fl)
ax2.set_ylabel('Precision',fontsize=fl)
plt.xticks([0, 0.1, 0.2, 0.3],fontsize=ft)
plt.yticks(fontsize=ft)
plt.tight_layout()
plt.show()
In [ ]:
detcls = set([])
for img in dict_img_detcls:
detcls = detcls.union(dict_img_detcls[img])
for c in dict_cls_name:
if c not in detcls:
print dict_cls_name[c]