halpecocotools 0.0.0__cp312-cp312-macosx_14_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- halpecocotools/__init__.py +1 -0
- halpecocotools/_mask.cpython-312-darwin.so +0 -0
- halpecocotools/coco.py +456 -0
- halpecocotools/cocoeval.py +818 -0
- halpecocotools/mask.py +103 -0
- halpecocotools-0.0.0.dist-info/METADATA +11 -0
- halpecocotools-0.0.0.dist-info/RECORD +9 -0
- halpecocotools-0.0.0.dist-info/WHEEL +5 -0
- halpecocotools-0.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,818 @@
|
|
1
|
+
__author__ = 'tsungyi, Haoyi Zhu'
|
2
|
+
|
3
|
+
import numpy as np
|
4
|
+
import datetime
|
5
|
+
import time
|
6
|
+
from collections import defaultdict
|
7
|
+
from . import mask as maskUtils
|
8
|
+
import copy
|
9
|
+
|
10
|
+
class COCOeval:
|
11
|
+
# Interface for evaluating detection on the Microsoft COCO dataset.
|
12
|
+
#
|
13
|
+
# The usage for CocoEval is as follows:
|
14
|
+
# cocoGt=..., cocoDt=... # load dataset and results
|
15
|
+
# E = CocoEval(cocoGt,cocoDt); # initialize CocoEval object
|
16
|
+
# E.params.recThrs = ...; # set parameters as desired
|
17
|
+
# E.evaluate(); # run per image evaluation
|
18
|
+
# E.accumulate(); # accumulate per image results
|
19
|
+
# E.summarize(); # display summary metrics of results
|
20
|
+
# For example usage see evalDemo.m and http://mscoco.org/.
|
21
|
+
#
|
22
|
+
# The evaluation parameters are as follows (defaults in brackets):
|
23
|
+
# imgIds - [all] N img ids to use for evaluation
|
24
|
+
# catIds - [all] K cat ids to use for evaluation
|
25
|
+
# iouThrs - [.5:.05:.95] T=10 IoU thresholds for evaluation
|
26
|
+
# recThrs - [0:.01:1] R=101 recall thresholds for evaluation
|
27
|
+
# areaRng - [...] A=4 object area ranges for evaluation
|
28
|
+
# maxDets - [1 10 100] M=3 thresholds on max detections per image
|
29
|
+
# iouType - ['segm'] set iouType to 'segm', 'bbox' or 'keypoints'
|
30
|
+
# iouType replaced the now DEPRECATED useSegm parameter.
|
31
|
+
# useCats - [1] if true use category labels for evaluation
|
32
|
+
# Note: if useCats=0 category labels are ignored as in proposal scoring.
|
33
|
+
# Note: multiple areaRngs [Ax2] and maxDets [Mx1] can be specified.
|
34
|
+
#
|
35
|
+
# evaluate(): evaluates detections on every image and every category and
|
36
|
+
# concats the results into the "evalImgs" with fields:
|
37
|
+
# dtIds - [1xD] id for each of the D detections (dt)
|
38
|
+
# gtIds - [1xG] id for each of the G ground truths (gt)
|
39
|
+
# dtMatches - [TxD] matching gt id at each IoU or 0
|
40
|
+
# gtMatches - [TxG] matching dt id at each IoU or 0
|
41
|
+
# dtScores - [1xD] confidence of each dt
|
42
|
+
# gtIgnore - [1xG] ignore flag for each gt
|
43
|
+
# dtIgnore - [TxD] ignore flag for each dt at each IoU
|
44
|
+
#
|
45
|
+
# accumulate(): accumulates the per-image, per-category evaluation
|
46
|
+
# results in "evalImgs" into the dictionary "eval" with fields:
|
47
|
+
# params - parameters used for evaluation
|
48
|
+
# date - date evaluation was performed
|
49
|
+
# counts - [T,R,K,A,M] parameter dimensions (see above)
|
50
|
+
# precision - [TxRxKxAxM] precision for every evaluation setting
|
51
|
+
# recall - [TxKxAxM] max recall for every evaluation setting
|
52
|
+
# Note: precision and recall==-1 for settings with no gt objects.
|
53
|
+
#
|
54
|
+
# See also coco, mask, pycocoDemo, pycocoEvalDemo
|
55
|
+
#
|
56
|
+
# The original Microsoft COCO Toolbox is written
|
57
|
+
# by Piotr Dollar and Tsung-Yi Lin, 2015.
|
58
|
+
# Licensed under the Simplified BSD License [see coco/license.txt]
|
59
|
+
#
|
60
|
+
# Updated and renamed to Halpe COCO Toolbox (cocohalpetools) \
|
61
|
+
# by Haoyi Zhu in 2021. The Halpe COCO Toolbox is
|
62
|
+
# developed to support wholebody human pose datasets,
|
63
|
+
# including Halpe Full-body and COCO WholeBody.
|
64
|
+
|
65
|
+
def __init__(self, cocoGt=None, cocoDt=None, iouType='segm'):
|
66
|
+
'''
|
67
|
+
Initialize CocoEval using coco APIs for gt and dt
|
68
|
+
:param cocoGt: coco object with ground truth annotations
|
69
|
+
:param cocoDt: coco object with detection results
|
70
|
+
:return: None
|
71
|
+
'''
|
72
|
+
if not iouType:
|
73
|
+
print('iouType not specified. use default iouType segm')
|
74
|
+
self.cocoGt = cocoGt # ground truth COCO API
|
75
|
+
self.cocoDt = cocoDt # detections COCO API
|
76
|
+
self.params = {} # evaluation parameters
|
77
|
+
self.evalImgs = defaultdict(list) # per-image per-category evaluation results [KxAxI] elements
|
78
|
+
self.eval = {} # accumulated evaluation results
|
79
|
+
self._gts = defaultdict(list) # gt for evaluation
|
80
|
+
self._dts = defaultdict(list) # dt for evaluation
|
81
|
+
self.params = Params(iouType=iouType) # parameters
|
82
|
+
self._paramsEval = {} # parameters for evaluation
|
83
|
+
self.stats = [] # result summarization
|
84
|
+
self.ious = {} # ious between all gts and dts
|
85
|
+
if not cocoGt is None:
|
86
|
+
self.params.imgIds = sorted(cocoGt.getImgIds())
|
87
|
+
self.params.catIds = sorted(cocoGt.getCatIds())
|
88
|
+
|
89
|
+
|
90
|
+
def _prepare(self):
|
91
|
+
'''
|
92
|
+
Prepare ._gts and ._dts for evaluation based on params
|
93
|
+
:return: None
|
94
|
+
'''
|
95
|
+
def _toMask(anns, coco):
|
96
|
+
# modify ann['segmentation'] by reference
|
97
|
+
for ann in anns:
|
98
|
+
rle = coco.annToRLE(ann)
|
99
|
+
ann['segmentation'] = rle
|
100
|
+
p = self.params
|
101
|
+
if p.useCats:
|
102
|
+
gts=self.cocoGt.loadAnns(self.cocoGt.getAnnIds(imgIds=p.imgIds, catIds=p.catIds))
|
103
|
+
dts=self.cocoDt.loadAnns(self.cocoDt.getAnnIds(imgIds=p.imgIds, catIds=p.catIds))
|
104
|
+
else:
|
105
|
+
gts=self.cocoGt.loadAnns(self.cocoGt.getAnnIds(imgIds=p.imgIds))
|
106
|
+
dts=self.cocoDt.loadAnns(self.cocoDt.getAnnIds(imgIds=p.imgIds))
|
107
|
+
|
108
|
+
# convert ground truth to mask if iouType == 'segm'
|
109
|
+
if p.iouType == 'segm':
|
110
|
+
_toMask(gts, self.cocoGt)
|
111
|
+
_toMask(dts, self.cocoDt)
|
112
|
+
# set ignore flag
|
113
|
+
for gt in gts:
|
114
|
+
gt['ignore'] = gt['ignore'] if 'ignore' in gt else 0
|
115
|
+
# gt['ignore'] = 'iscrowd' in gt and gt['iscrowd']
|
116
|
+
if p.iouType == 'keypoints':
|
117
|
+
if len(gt['keypoints']) % 133 == 0 or len(gt['keypoints']) % 136 == 0:
|
118
|
+
_ignore = gt['ignore']
|
119
|
+
gt['ignore'] = dict()
|
120
|
+
body_kp = np.array(gt['keypoints'][:-116*3])
|
121
|
+
foot_kp = np.array(gt['keypoints'][-116*3:-110*3])
|
122
|
+
face_kp = np.array(gt['keypoints'][-110*3:-42*3])
|
123
|
+
hand_kp = np.array(gt['keypoints'][-42*3:])
|
124
|
+
fullbody_kp = np.array(gt['keypoints'])
|
125
|
+
|
126
|
+
vg_body = body_kp[2::3]
|
127
|
+
vg_foot = foot_kp[2::3]
|
128
|
+
vg_face = face_kp[2::3]
|
129
|
+
vg_hand = hand_kp[2::3]
|
130
|
+
vg_fullbody = fullbody_kp[2::3]
|
131
|
+
k1_body = np.count_nonzero(vg_body > 0)
|
132
|
+
k1_foot = np.count_nonzero(vg_foot > 0)
|
133
|
+
k1_face = np.count_nonzero(vg_face > 0)
|
134
|
+
k1_hand = np.count_nonzero(vg_hand > 0)
|
135
|
+
k1_fullbody = np.count_nonzero(vg_fullbody > 0)
|
136
|
+
|
137
|
+
gt['ignore']['body'] = (k1_body == 0) or _ignore
|
138
|
+
gt['ignore']['foot'] = (k1_foot == 0) or _ignore
|
139
|
+
gt['ignore']['face'] = (k1_face == 0) or _ignore
|
140
|
+
gt['ignore']['hand'] = (k1_hand == 0) or _ignore
|
141
|
+
gt['ignore']['fullbody'] = (k1_fullbody == 0) or _ignore
|
142
|
+
else:
|
143
|
+
gt['ignore'] = (gt['num_keypoints'] == 0) or gt['ignore']
|
144
|
+
self._gts = defaultdict(list) # gt for evaluation
|
145
|
+
self._dts = defaultdict(list) # dt for evaluation
|
146
|
+
for gt in gts:
|
147
|
+
self._gts[gt['image_id'], gt['category_id']].append(gt)
|
148
|
+
for dt in dts:
|
149
|
+
vd = np.array(dt['keypoints'])[2::3]
|
150
|
+
if len(vd[vd>0]) == 0:
|
151
|
+
continue
|
152
|
+
self._dts[dt['image_id'], dt['category_id']].append(dt)
|
153
|
+
self.evalImgs = defaultdict(list) # per-image per-category evaluation results
|
154
|
+
self.eval = {} # accumulated evaluation results
|
155
|
+
|
156
|
+
def evaluate(self):
|
157
|
+
'''
|
158
|
+
Run per image evaluation on given images and store results (a list of dict) in self.evalImgs
|
159
|
+
:return: None
|
160
|
+
'''
|
161
|
+
tic = time.time()
|
162
|
+
print('Running per image evaluation...')
|
163
|
+
p = self.params
|
164
|
+
# add backward compatibility if useSegm is specified in params
|
165
|
+
if not p.useSegm is None:
|
166
|
+
p.iouType = 'segm' if p.useSegm == 1 else 'bbox'
|
167
|
+
print('useSegm (deprecated) is not None. Running {} evaluation'.format(p.iouType))
|
168
|
+
print('Evaluate annotation type *{}*'.format(p.iouType))
|
169
|
+
p.imgIds = list(np.unique(p.imgIds))
|
170
|
+
if p.useCats:
|
171
|
+
p.catIds = list(np.unique(p.catIds))
|
172
|
+
p.maxDets = sorted(p.maxDets)
|
173
|
+
self.params=p
|
174
|
+
|
175
|
+
self._prepare()
|
176
|
+
# loop through images, area range, max detection number
|
177
|
+
catIds = p.catIds if p.useCats else [-1]
|
178
|
+
|
179
|
+
if p.iouType == 'segm' or p.iouType == 'bbox':
|
180
|
+
computeIoU = self.computeIoU
|
181
|
+
elif p.iouType == 'keypoints':
|
182
|
+
computeIoU = self.computeOks
|
183
|
+
self.ious = {(imgId, catId): computeIoU(imgId, catId) \
|
184
|
+
for imgId in p.imgIds
|
185
|
+
for catId in catIds}
|
186
|
+
|
187
|
+
evaluateImg = self.evaluateImg
|
188
|
+
maxDet = p.maxDets[-1]
|
189
|
+
self.evalImgs = [evaluateImg(imgId, catId, areaRng, maxDet)
|
190
|
+
for catId in catIds
|
191
|
+
for areaRng in p.areaRng
|
192
|
+
for imgId in p.imgIds
|
193
|
+
]
|
194
|
+
self._paramsEval = copy.deepcopy(self.params)
|
195
|
+
toc = time.time()
|
196
|
+
print('DONE (t={:0.2f}s).'.format(toc-tic))
|
197
|
+
|
198
|
+
def computeIoU(self, imgId, catId):
|
199
|
+
p = self.params
|
200
|
+
if p.useCats:
|
201
|
+
gt = self._gts[imgId,catId]
|
202
|
+
dt = self._dts[imgId,catId]
|
203
|
+
else:
|
204
|
+
gt = [_ for cId in p.catIds for _ in self._gts[imgId,cId]]
|
205
|
+
dt = [_ for cId in p.catIds for _ in self._dts[imgId,cId]]
|
206
|
+
if len(gt) == 0 and len(dt) ==0:
|
207
|
+
return []
|
208
|
+
inds = np.argsort([-d['score'] for d in dt], kind='mergesort')
|
209
|
+
dt = [dt[i] for i in inds]
|
210
|
+
if len(dt) > p.maxDets[-1]:
|
211
|
+
dt=dt[0:p.maxDets[-1]]
|
212
|
+
|
213
|
+
if p.iouType == 'segm':
|
214
|
+
g = [g['segmentation'] for g in gt]
|
215
|
+
d = [d['segmentation'] for d in dt]
|
216
|
+
elif p.iouType == 'bbox':
|
217
|
+
g = [g['bbox'] for g in gt]
|
218
|
+
d = [d['bbox'] for d in dt]
|
219
|
+
else:
|
220
|
+
raise Exception('unknown iouType for iou computation')
|
221
|
+
|
222
|
+
# compute iou between each dt and gt region
|
223
|
+
iscrowd = [int(o['iscrowd']) for o in gt]
|
224
|
+
ious = maskUtils.iou(d,g,iscrowd)
|
225
|
+
return ious
|
226
|
+
|
227
|
+
def computeOks(self, imgId, catId):
|
228
|
+
parts = ['body', 'foot', 'face', 'hand', 'fullbody']
|
229
|
+
_ious = {}
|
230
|
+
for part in parts:
|
231
|
+
p = self.params
|
232
|
+
# dimention here should be Nxm
|
233
|
+
gts = self._gts[imgId, catId]
|
234
|
+
dts = self._dts[imgId, catId]
|
235
|
+
inds = np.argsort([-d['score'] for d in dts], kind='mergesort')
|
236
|
+
dts = [dts[i] for i in inds]
|
237
|
+
if len(dts) > p.maxDets[-1]:
|
238
|
+
dts = dts[0:p.maxDets[-1]]
|
239
|
+
# if len(gts) == 0 and len(dts) == 0:
|
240
|
+
if len(gts) == 0 or len(dts) == 0:
|
241
|
+
_ious[part] = []
|
242
|
+
continue
|
243
|
+
ious = np.zeros((len(dts), len(gts)))
|
244
|
+
if len(gts[0]['keypoints']) == 136 * 3:
|
245
|
+
sigmas = np.array([.26, .25, .25, .35, .35, .79, .79, .72, .72, .62,.62, 1.07, 1.07, .87, .87, .89, .89, .8,.8,.8,.89, .89, .89, .89, .89, .89,
|
246
|
+
.15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15,
|
247
|
+
.15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15,
|
248
|
+
.15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15,
|
249
|
+
.15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15,
|
250
|
+
.15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15])/10.0
|
251
|
+
body_kpnum = 20
|
252
|
+
foot_kpnum = 6
|
253
|
+
face_kpnum = 68
|
254
|
+
hand_kpnum = 21 * 2
|
255
|
+
|
256
|
+
elif len(gts[0]['keypoints']) == 133 * 3: # surport for COCO WholeBody
|
257
|
+
sigmas = np.array([.26, .25, .25, .35, .35, .79, .79, .72, .72, .62,.62, 1.07, 1.07, .87, .87, .89, .89, .89, .89, .89, .89, .89, .89,
|
258
|
+
.15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15,
|
259
|
+
.15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15,
|
260
|
+
.15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15,
|
261
|
+
.15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15,
|
262
|
+
.15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15, .15])/10.0
|
263
|
+
body_kpnum = 17
|
264
|
+
foot_kpnum = 6
|
265
|
+
face_kpnum = 68
|
266
|
+
hand_kpnum = 21 * 2
|
267
|
+
|
268
|
+
if part == 'body':
|
269
|
+
sigmas = sigmas[0 : body_kpnum]
|
270
|
+
elif part == 'foot':
|
271
|
+
sigmas = sigmas[body_kpnum : body_kpnum + foot_kpnum]
|
272
|
+
elif part == 'face':
|
273
|
+
sigmas = sigmas[body_kpnum + foot_kpnum : body_kpnum + foot_kpnum + face_kpnum]
|
274
|
+
elif part == 'hand':
|
275
|
+
sigmas = sigmas[body_kpnum + foot_kpnum + face_kpnum:]
|
276
|
+
|
277
|
+
vars = (sigmas * 2)**2
|
278
|
+
k = len(sigmas)
|
279
|
+
from tkinter import _flatten
|
280
|
+
# compute oks between each detection and ground truth object
|
281
|
+
for j, gt in enumerate(gts):
|
282
|
+
# create bounds for ignore regions(double the gt bbox)
|
283
|
+
if part == 'body':
|
284
|
+
g = np.array(gt['keypoints'][0 : body_kpnum*3],dtype=np.float32)
|
285
|
+
elif part == 'foot':
|
286
|
+
g = np.array(gt['keypoints'][body_kpnum*3 : (body_kpnum + foot_kpnum)*3],dtype=np.float32)
|
287
|
+
elif part == 'face':
|
288
|
+
g = np.array(gt['keypoints'][(body_kpnum + foot_kpnum)*3 : (body_kpnum + foot_kpnum + face_kpnum)*3],dtype=np.float32)
|
289
|
+
elif part == 'hand':
|
290
|
+
g = np.array(gt['keypoints'][(body_kpnum + foot_kpnum + face_kpnum)*3:],dtype=np.float32)
|
291
|
+
else:
|
292
|
+
g = np.array(gt['keypoints'],dtype=np.float32)
|
293
|
+
|
294
|
+
xg = g[0::3]; yg = g[1::3]; vg = g[2::3]
|
295
|
+
k1 = np.count_nonzero(vg > 0)
|
296
|
+
bb = gt['bbox']
|
297
|
+
x0 = bb[0] - bb[2]; x1 = bb[0] + bb[2] * 2
|
298
|
+
y0 = bb[1] - bb[3]; y1 = bb[1] + bb[3] * 2
|
299
|
+
for i, dt in enumerate(dts):
|
300
|
+
if part == 'body':
|
301
|
+
d = np.array(dt['keypoints'][0 : body_kpnum*3],dtype=np.float32)
|
302
|
+
elif part == 'foot':
|
303
|
+
d = np.array(dt['keypoints'][body_kpnum*3 : (body_kpnum + foot_kpnum)*3],dtype=np.float32)
|
304
|
+
elif part == 'face':
|
305
|
+
d = np.array(dt['keypoints'][(body_kpnum + foot_kpnum)*3 : (body_kpnum + foot_kpnum + face_kpnum)*3],dtype=np.float32)
|
306
|
+
elif part == 'hand':
|
307
|
+
d = np.array(dt['keypoints'][(body_kpnum + foot_kpnum + face_kpnum)*3:],dtype=np.float32)
|
308
|
+
else:
|
309
|
+
d = np.array(dt['keypoints'], dtype=np.float32)
|
310
|
+
|
311
|
+
xd = d[0::3]; yd = d[1::3]
|
312
|
+
if k1>0:
|
313
|
+
# measure the per-keypoint distance if keypoints visible
|
314
|
+
dx = xd - xg
|
315
|
+
dy = yd - yg
|
316
|
+
else:
|
317
|
+
# measure minimum distance to keypoints in (x0,y0) & (x1,y1)
|
318
|
+
z = np.zeros((k))
|
319
|
+
dx = np.max((z, x0-xd),axis=0)+np.max((z, xd-x1),axis=0)
|
320
|
+
dy = np.max((z, y0-yd),axis=0)+np.max((z, yd-y1),axis=0)
|
321
|
+
e = (dx**2 + dy**2) / vars / (gt['area']+np.spacing(1)) / 2
|
322
|
+
if k1 > 0:
|
323
|
+
e=e[vg > 0]
|
324
|
+
ious[i, j] = np.sum(np.exp(-e)) / e.shape[0]
|
325
|
+
_ious[part] = ious
|
326
|
+
return _ious
|
327
|
+
|
328
|
+
def evaluateImg(self, imgId, catId, aRng, maxDet):
|
329
|
+
'''
|
330
|
+
perform evaluation for single category and image
|
331
|
+
:return: dict (single image results)
|
332
|
+
'''
|
333
|
+
if self.params.iouType == 'keypoints':
|
334
|
+
parts = ['body', 'foot', 'face', 'hand', 'fullbody']
|
335
|
+
res = {}
|
336
|
+
for part in parts:
|
337
|
+
p = self.params
|
338
|
+
if p.useCats:
|
339
|
+
gt = self._gts[imgId,catId]
|
340
|
+
dt = self._dts[imgId,catId]
|
341
|
+
else:
|
342
|
+
gt = [_ for cId in p.catIds for _ in self._gts[imgId,cId]]
|
343
|
+
dt = [_ for cId in p.catIds for _ in self._dts[imgId,cId]]
|
344
|
+
if len(gt) == 0 and len(dt) ==0:
|
345
|
+
res[part] = None
|
346
|
+
continue
|
347
|
+
|
348
|
+
for g in gt:
|
349
|
+
if g['ignore'][part] or (g['area']<aRng[0] or g['area']>aRng[1]):
|
350
|
+
g['_ignore'] = 1
|
351
|
+
else:
|
352
|
+
g['_ignore'] = 0
|
353
|
+
|
354
|
+
# sort dt highest score first, sort gt ignore last
|
355
|
+
gtind = np.argsort([g['_ignore'] for g in gt], kind='mergesort')
|
356
|
+
gt = [gt[i] for i in gtind]
|
357
|
+
dtind = np.argsort([-d['score'] for d in dt], kind='mergesort')
|
358
|
+
dt = [dt[i] for i in dtind[0:maxDet]]
|
359
|
+
iscrowd = [int(o['iscrowd']) for o in gt]
|
360
|
+
# load computed ious
|
361
|
+
ious = self.ious[imgId, catId][part][:, gtind] if len(self.ious[imgId, catId][part]) > 0 else self.ious[imgId, catId][part]
|
362
|
+
|
363
|
+
T = len(p.iouThrs)
|
364
|
+
G = len(gt)
|
365
|
+
D = len(dt)
|
366
|
+
gtm = np.zeros((T,G))
|
367
|
+
dtm = np.zeros((T,D))
|
368
|
+
gtIg = np.array([g['_ignore'] for g in gt])
|
369
|
+
dtIg = np.zeros((T,D))
|
370
|
+
if not len(ious)==0:
|
371
|
+
for tind, t in enumerate(p.iouThrs):
|
372
|
+
for dind, d in enumerate(dt):
|
373
|
+
# information about best match so far (m=-1 -> unmatched)
|
374
|
+
iou = min([t,1-1e-10])
|
375
|
+
m = -1
|
376
|
+
for gind, g in enumerate(gt):
|
377
|
+
# if this gt already matched, and not a crowd, continue
|
378
|
+
if gtm[tind,gind]>0 and not iscrowd[gind]:
|
379
|
+
continue
|
380
|
+
# if dt matched to reg gt, and on ignore gt, stop
|
381
|
+
if m>-1 and gtIg[m]==0 and gtIg[gind]==1:
|
382
|
+
break
|
383
|
+
# continue to next gt unless better match made
|
384
|
+
if ious[dind,gind] < iou:
|
385
|
+
continue
|
386
|
+
# if match successful and best so far, store appropriately
|
387
|
+
iou=ious[dind,gind]
|
388
|
+
m=gind
|
389
|
+
# if match made store id of match for both dt and gt
|
390
|
+
if m ==-1:
|
391
|
+
continue
|
392
|
+
dtIg[tind,dind] = gtIg[m]
|
393
|
+
dtm[tind,dind] = gt[m]['id']
|
394
|
+
gtm[tind,m] = d['id']
|
395
|
+
# set unmatched detections outside of area range to ignore
|
396
|
+
a = np.array([d['area']<aRng[0] or d['area']>aRng[1] for d in dt]).reshape((1, len(dt)))
|
397
|
+
dtIg = np.logical_or(dtIg, np.logical_and(dtm==0, np.repeat(a,T,0)))
|
398
|
+
# store results for given image and category
|
399
|
+
res[part]={
|
400
|
+
'image_id': imgId,
|
401
|
+
'category_id': catId,
|
402
|
+
'aRng': aRng,
|
403
|
+
'maxDet': maxDet,
|
404
|
+
'dtIds': [d['id'] for d in dt],
|
405
|
+
'gtIds': [g['id'] for g in gt],
|
406
|
+
'dtMatches': dtm,
|
407
|
+
'gtMatches': gtm,
|
408
|
+
'dtScores': [d['score'] for d in dt],
|
409
|
+
'gtIgnore': gtIg,
|
410
|
+
'dtIgnore': dtIg,
|
411
|
+
}
|
412
|
+
return res
|
413
|
+
else:
|
414
|
+
p = self.params
|
415
|
+
if p.useCats:
|
416
|
+
gt = self._gts[imgId,catId]
|
417
|
+
dt = self._dts[imgId,catId]
|
418
|
+
else:
|
419
|
+
gt = [_ for cId in p.catIds for _ in self._gts[imgId,cId]]
|
420
|
+
dt = [_ for cId in p.catIds for _ in self._dts[imgId,cId]]
|
421
|
+
if len(gt) == 0 and len(dt) ==0:
|
422
|
+
return None
|
423
|
+
|
424
|
+
for g in gt:
|
425
|
+
if g['ignore'] or (g['area']<aRng[0] or g['area']>aRng[1]):
|
426
|
+
g['_ignore'] = 1
|
427
|
+
else:
|
428
|
+
g['_ignore'] = 0
|
429
|
+
|
430
|
+
# sort dt highest score first, sort gt ignore last
|
431
|
+
gtind = np.argsort([g['_ignore'] for g in gt], kind='mergesort')
|
432
|
+
gt = [gt[i] for i in gtind]
|
433
|
+
dtind = np.argsort([-d['score'] for d in dt], kind='mergesort')
|
434
|
+
dt = [dt[i] for i in dtind[0:maxDet]]
|
435
|
+
iscrowd = [int(o['iscrowd']) for o in gt]
|
436
|
+
# load computed ious
|
437
|
+
ious = self.ious[imgId, catId][:, gtind] if len(self.ious[imgId, catId]) > 0 else self.ious[imgId, catId]
|
438
|
+
|
439
|
+
T = len(p.iouThrs)
|
440
|
+
G = len(gt)
|
441
|
+
D = len(dt)
|
442
|
+
gtm = np.zeros((T,G))
|
443
|
+
dtm = np.zeros((T,D))
|
444
|
+
gtIg = np.array([g['_ignore'] for g in gt])
|
445
|
+
dtIg = np.zeros((T,D))
|
446
|
+
if not len(ious)==0:
|
447
|
+
for tind, t in enumerate(p.iouThrs):
|
448
|
+
for dind, d in enumerate(dt):
|
449
|
+
# information about best match so far (m=-1 -> unmatched)
|
450
|
+
iou = min([t,1-1e-10])
|
451
|
+
m = -1
|
452
|
+
for gind, g in enumerate(gt):
|
453
|
+
# if this gt already matched, and not a crowd, continue
|
454
|
+
if gtm[tind,gind]>0 and not iscrowd[gind]:
|
455
|
+
continue
|
456
|
+
# if dt matched to reg gt, and on ignore gt, stop
|
457
|
+
if m>-1 and gtIg[m]==0 and gtIg[gind]==1:
|
458
|
+
break
|
459
|
+
# continue to next gt unless better match made
|
460
|
+
if ious[dind,gind] < iou:
|
461
|
+
continue
|
462
|
+
# if match successful and best so far, store appropriately
|
463
|
+
iou=ious[dind,gind]
|
464
|
+
m=gind
|
465
|
+
# if match made store id of match for both dt and gt
|
466
|
+
if m ==-1:
|
467
|
+
continue
|
468
|
+
dtIg[tind,dind] = gtIg[m]
|
469
|
+
dtm[tind,dind] = gt[m]['id']
|
470
|
+
gtm[tind,m] = d['id']
|
471
|
+
# set unmatched detections outside of area range to ignore
|
472
|
+
a = np.array([d['area']<aRng[0] or d['area']>aRng[1] for d in dt]).reshape((1, len(dt)))
|
473
|
+
dtIg = np.logical_or(dtIg, np.logical_and(dtm==0, np.repeat(a,T,0)))
|
474
|
+
# store results for given image and category
|
475
|
+
return {
|
476
|
+
'image_id': imgId,
|
477
|
+
'category_id': catId,
|
478
|
+
'aRng': aRng,
|
479
|
+
'maxDet': maxDet,
|
480
|
+
'dtIds': [d['id'] for d in dt],
|
481
|
+
'gtIds': [g['id'] for g in gt],
|
482
|
+
'dtMatches': dtm,
|
483
|
+
'gtMatches': gtm,
|
484
|
+
'dtScores': [d['score'] for d in dt],
|
485
|
+
'gtIgnore': gtIg,
|
486
|
+
'dtIgnore': dtIg,
|
487
|
+
}
|
488
|
+
return res
|
489
|
+
|
490
|
+
def accumulate(self, p = None):
|
491
|
+
'''
|
492
|
+
Accumulate per image evaluation results and store the result in self.eval
|
493
|
+
:param p: input params for evaluation
|
494
|
+
:return: None
|
495
|
+
'''
|
496
|
+
print('Accumulating evaluation results...')
|
497
|
+
tic = time.time()
|
498
|
+
if not self.evalImgs:
|
499
|
+
print('Please run evaluate() first')
|
500
|
+
if self.params.iouType == 'keypoints':
|
501
|
+
parts = ['body', 'foot', 'face', 'hand', 'fullbody']
|
502
|
+
for part in parts:
|
503
|
+
# allows input customized parameters
|
504
|
+
if p is None:
|
505
|
+
p = self.params
|
506
|
+
p.catIds = p.catIds if p.useCats == 1 else [-1]
|
507
|
+
T = len(p.iouThrs)
|
508
|
+
R = len(p.recThrs)
|
509
|
+
K = len(p.catIds) if p.useCats else 1
|
510
|
+
A = len(p.areaRng)
|
511
|
+
M = len(p.maxDets)
|
512
|
+
precision = -np.ones((T,R,K,A,M)) # -1 for the precision of absent categories
|
513
|
+
recall = -np.ones((T,K,A,M))
|
514
|
+
scores = -np.ones((T,R,K,A,M))
|
515
|
+
|
516
|
+
# create dictionary for future indexing
|
517
|
+
_pe = self._paramsEval
|
518
|
+
catIds = _pe.catIds if _pe.useCats else [-1]
|
519
|
+
setK = set(catIds)
|
520
|
+
setA = set(map(tuple, _pe.areaRng))
|
521
|
+
setM = set(_pe.maxDets)
|
522
|
+
setI = set(_pe.imgIds)
|
523
|
+
# get inds to evaluate
|
524
|
+
k_list = [n for n, k in enumerate(p.catIds) if k in setK]
|
525
|
+
m_list = [m for n, m in enumerate(p.maxDets) if m in setM]
|
526
|
+
a_list = [n for n, a in enumerate(map(lambda x: tuple(x), p.areaRng)) if a in setA]
|
527
|
+
i_list = [n for n, i in enumerate(p.imgIds) if i in setI]
|
528
|
+
I0 = len(_pe.imgIds)
|
529
|
+
A0 = len(_pe.areaRng)
|
530
|
+
# retrieve E at each category, area range, and max number of detections
|
531
|
+
|
532
|
+
for k, k0 in enumerate(k_list):
|
533
|
+
Nk = k0*A0*I0
|
534
|
+
for a, a0 in enumerate(a_list):
|
535
|
+
Na = a0*I0
|
536
|
+
for m, maxDet in enumerate(m_list):
|
537
|
+
E = [self.evalImgs[Nk + Na + i][part] for i in i_list]
|
538
|
+
E = [e for e in E if not e is None]
|
539
|
+
if len(E) == 0:
|
540
|
+
continue
|
541
|
+
dtScores = np.concatenate([e['dtScores'][0:maxDet] for e in E])
|
542
|
+
|
543
|
+
# different sorting method generates slightly different results.
|
544
|
+
# mergesort is used to be consistent as Matlab implementation.
|
545
|
+
inds = np.argsort(-dtScores, kind='mergesort')
|
546
|
+
dtScoresSorted = dtScores[inds]
|
547
|
+
|
548
|
+
dtm = np.concatenate([e['dtMatches'][:,0:maxDet] for e in E], axis=1)[:,inds]
|
549
|
+
dtIg = np.concatenate([e['dtIgnore'][:,0:maxDet] for e in E], axis=1)[:,inds]
|
550
|
+
gtIg = np.concatenate([e['gtIgnore'] for e in E])
|
551
|
+
npig = np.count_nonzero(gtIg==0 )
|
552
|
+
if npig == 0:
|
553
|
+
continue
|
554
|
+
tps = np.logical_and( dtm, np.logical_not(dtIg) )
|
555
|
+
fps = np.logical_and(np.logical_not(dtm), np.logical_not(dtIg) )
|
556
|
+
|
557
|
+
tp_sum = np.cumsum(tps, axis=1).astype(dtype=np.float)
|
558
|
+
fp_sum = np.cumsum(fps, axis=1).astype(dtype=np.float)
|
559
|
+
for t, (tp, fp) in enumerate(zip(tp_sum, fp_sum)):
|
560
|
+
tp = np.array(tp)
|
561
|
+
fp = np.array(fp)
|
562
|
+
nd = len(tp)
|
563
|
+
rc = tp / npig
|
564
|
+
pr = tp / (fp+tp+np.spacing(1))
|
565
|
+
q = np.zeros((R,))
|
566
|
+
ss = np.zeros((R,))
|
567
|
+
|
568
|
+
if nd:
|
569
|
+
recall[t,k,a,m] = rc[-1]
|
570
|
+
else:
|
571
|
+
recall[t,k,a,m] = 0
|
572
|
+
|
573
|
+
# numpy is slow without cython optimization for accessing elements
|
574
|
+
# use python array gets significant speed improvement
|
575
|
+
pr = pr.tolist(); q = q.tolist()
|
576
|
+
|
577
|
+
for i in range(nd-1, 0, -1):
|
578
|
+
if pr[i] > pr[i-1]:
|
579
|
+
pr[i-1] = pr[i]
|
580
|
+
|
581
|
+
inds = np.searchsorted(rc, p.recThrs, side='left')
|
582
|
+
try:
|
583
|
+
for ri, pi in enumerate(inds):
|
584
|
+
q[ri] = pr[pi]
|
585
|
+
ss[ri] = dtScoresSorted[pi]
|
586
|
+
except:
|
587
|
+
pass
|
588
|
+
precision[t,:,k,a,m] = np.array(q)
|
589
|
+
scores[t,:,k,a,m] = np.array(ss)
|
590
|
+
self.eval[part] = {
|
591
|
+
'params': p,
|
592
|
+
'counts': [T, R, K, A, M],
|
593
|
+
'date': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
|
594
|
+
'precision': precision,
|
595
|
+
'recall': recall,
|
596
|
+
'scores': scores,
|
597
|
+
}
|
598
|
+
else:
|
599
|
+
if p is None:
|
600
|
+
p = self.params
|
601
|
+
p.catIds = p.catIds if p.useCats == 1 else [-1]
|
602
|
+
T = len(p.iouThrs)
|
603
|
+
R = len(p.recThrs)
|
604
|
+
K = len(p.catIds) if p.useCats else 1
|
605
|
+
A = len(p.areaRng)
|
606
|
+
M = len(p.maxDets)
|
607
|
+
precision = -np.ones((T,R,K,A,M)) # -1 for the precision of absent categories
|
608
|
+
recall = -np.ones((T,K,A,M))
|
609
|
+
scores = -np.ones((T,R,K,A,M))
|
610
|
+
|
611
|
+
# create dictionary for future indexing
|
612
|
+
_pe = self._paramsEval
|
613
|
+
catIds = _pe.catIds if _pe.useCats else [-1]
|
614
|
+
setK = set(catIds)
|
615
|
+
setA = set(map(tuple, _pe.areaRng))
|
616
|
+
setM = set(_pe.maxDets)
|
617
|
+
setI = set(_pe.imgIds)
|
618
|
+
# get inds to evaluate
|
619
|
+
k_list = [n for n, k in enumerate(p.catIds) if k in setK]
|
620
|
+
m_list = [m for n, m in enumerate(p.maxDets) if m in setM]
|
621
|
+
a_list = [n for n, a in enumerate(map(lambda x: tuple(x), p.areaRng)) if a in setA]
|
622
|
+
i_list = [n for n, i in enumerate(p.imgIds) if i in setI]
|
623
|
+
I0 = len(_pe.imgIds)
|
624
|
+
A0 = len(_pe.areaRng)
|
625
|
+
# retrieve E at each category, area range, and max number of detections
|
626
|
+
|
627
|
+
for k, k0 in enumerate(k_list):
|
628
|
+
Nk = k0*A0*I0
|
629
|
+
for a, a0 in enumerate(a_list):
|
630
|
+
Na = a0*I0
|
631
|
+
for m, maxDet in enumerate(m_list):
|
632
|
+
E = [self.evalImgs[Nk + Na + i] for i in i_list]
|
633
|
+
E = [e for e in E if not e is None]
|
634
|
+
if len(E) == 0:
|
635
|
+
continue
|
636
|
+
dtScores = np.concatenate([e['dtScores'][0:maxDet] for e in E])
|
637
|
+
|
638
|
+
# different sorting method generates slightly different results.
|
639
|
+
# mergesort is used to be consistent as Matlab implementation.
|
640
|
+
inds = np.argsort(-dtScores, kind='mergesort')
|
641
|
+
dtScoresSorted = dtScores[inds]
|
642
|
+
|
643
|
+
dtm = np.concatenate([e['dtMatches'][:,0:maxDet] for e in E], axis=1)[:,inds]
|
644
|
+
dtIg = np.concatenate([e['dtIgnore'][:,0:maxDet] for e in E], axis=1)[:,inds]
|
645
|
+
gtIg = np.concatenate([e['gtIgnore'] for e in E])
|
646
|
+
npig = np.count_nonzero(gtIg==0 )
|
647
|
+
if npig == 0:
|
648
|
+
continue
|
649
|
+
tps = np.logical_and( dtm, np.logical_not(dtIg) )
|
650
|
+
fps = np.logical_and(np.logical_not(dtm), np.logical_not(dtIg) )
|
651
|
+
|
652
|
+
tp_sum = np.cumsum(tps, axis=1).astype(dtype=np.float)
|
653
|
+
fp_sum = np.cumsum(fps, axis=1).astype(dtype=np.float)
|
654
|
+
for t, (tp, fp) in enumerate(zip(tp_sum, fp_sum)):
|
655
|
+
tp = np.array(tp)
|
656
|
+
fp = np.array(fp)
|
657
|
+
nd = len(tp)
|
658
|
+
rc = tp / npig
|
659
|
+
pr = tp / (fp+tp+np.spacing(1))
|
660
|
+
q = np.zeros((R,))
|
661
|
+
ss = np.zeros((R,))
|
662
|
+
|
663
|
+
if nd:
|
664
|
+
recall[t,k,a,m] = rc[-1]
|
665
|
+
else:
|
666
|
+
recall[t,k,a,m] = 0
|
667
|
+
|
668
|
+
# numpy is slow without cython optimization for accessing elements
|
669
|
+
# use python array gets significant speed improvement
|
670
|
+
pr = pr.tolist(); q = q.tolist()
|
671
|
+
|
672
|
+
for i in range(nd-1, 0, -1):
|
673
|
+
if pr[i] > pr[i-1]:
|
674
|
+
pr[i-1] = pr[i]
|
675
|
+
|
676
|
+
inds = np.searchsorted(rc, p.recThrs, side='left')
|
677
|
+
try:
|
678
|
+
for ri, pi in enumerate(inds):
|
679
|
+
q[ri] = pr[pi]
|
680
|
+
ss[ri] = dtScoresSorted[pi]
|
681
|
+
except:
|
682
|
+
pass
|
683
|
+
precision[t,:,k,a,m] = np.array(q)
|
684
|
+
scores[t,:,k,a,m] = np.array(ss)
|
685
|
+
self.eval = {
|
686
|
+
'params': p,
|
687
|
+
'counts': [T, R, K, A, M],
|
688
|
+
'date': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
|
689
|
+
'precision': precision,
|
690
|
+
'recall': recall,
|
691
|
+
'scores': scores,
|
692
|
+
}
|
693
|
+
|
694
|
+
toc = time.time()
|
695
|
+
print('DONE (t={:0.2f}s).'.format( toc-tic))
|
696
|
+
|
697
|
+
def summarize(self):
|
698
|
+
'''
|
699
|
+
Compute and display summary metrics for evaluation results.
|
700
|
+
Note this functin can *only* be applied on the default parameter setting
|
701
|
+
'''
|
702
|
+
def _summarize( ap=1, iouThr=None, areaRng='all', maxDets=100, part=None):
|
703
|
+
p = self.params
|
704
|
+
iStr = ' {:<18} {} @[ IoU={:<9} | area={:>6s} | maxDets={:>3d} ] = {:0.3f}'
|
705
|
+
titleStr = 'Average Precision' if ap == 1 else 'Average Recall'
|
706
|
+
typeStr = '(AP)' if ap==1 else '(AR)'
|
707
|
+
iouStr = '{:0.2f}:{:0.2f}'.format(p.iouThrs[0], p.iouThrs[-1]) \
|
708
|
+
if iouThr is None else '{:0.2f}'.format(iouThr)
|
709
|
+
|
710
|
+
aind = [i for i, aRng in enumerate(p.areaRngLbl) if aRng == areaRng]
|
711
|
+
mind = [i for i, mDet in enumerate(p.maxDets) if mDet == maxDets]
|
712
|
+
if ap == 1:
|
713
|
+
# dimension of precision: [TxRxKxAxM]
|
714
|
+
if part:
|
715
|
+
s = self.eval[part]['precision']
|
716
|
+
else:
|
717
|
+
s = self.eval['precision']
|
718
|
+
# IoU
|
719
|
+
if iouThr is not None:
|
720
|
+
t = np.where(iouThr == p.iouThrs)[0]
|
721
|
+
s = s[t]
|
722
|
+
s = s[:,:,:,aind,mind]
|
723
|
+
else:
|
724
|
+
# dimension of recall: [TxKxAxM]
|
725
|
+
if part:
|
726
|
+
s = self.eval[part]['recall']
|
727
|
+
else:
|
728
|
+
s = self.eval['recall']
|
729
|
+
if iouThr is not None:
|
730
|
+
t = np.where(iouThr == p.iouThrs)[0]
|
731
|
+
s = s[t]
|
732
|
+
s = s[:,:,aind,mind]
|
733
|
+
if len(s[s>-1])==0:
|
734
|
+
mean_s = -1
|
735
|
+
else:
|
736
|
+
mean_s = np.mean(s[s>-1])
|
737
|
+
print(iStr.format(titleStr, typeStr, iouStr, areaRng, maxDets, mean_s))
|
738
|
+
return mean_s
|
739
|
+
def _summarizeDets():
|
740
|
+
stats = np.zeros((12,))
|
741
|
+
stats[0] = _summarize(1)
|
742
|
+
stats[1] = _summarize(1, iouThr=.5, maxDets=self.params.maxDets[2])
|
743
|
+
stats[2] = _summarize(1, iouThr=.75, maxDets=self.params.maxDets[2])
|
744
|
+
stats[3] = _summarize(1, areaRng='small', maxDets=self.params.maxDets[2])
|
745
|
+
stats[4] = _summarize(1, areaRng='medium', maxDets=self.params.maxDets[2])
|
746
|
+
stats[5] = _summarize(1, areaRng='large', maxDets=self.params.maxDets[2])
|
747
|
+
stats[6] = _summarize(0, maxDets=self.params.maxDets[0])
|
748
|
+
stats[7] = _summarize(0, maxDets=self.params.maxDets[1])
|
749
|
+
stats[8] = _summarize(0, maxDets=self.params.maxDets[2])
|
750
|
+
stats[9] = _summarize(0, areaRng='small', maxDets=self.params.maxDets[2])
|
751
|
+
stats[10] = _summarize(0, areaRng='medium', maxDets=self.params.maxDets[2])
|
752
|
+
stats[11] = _summarize(0, areaRng='large', maxDets=self.params.maxDets[2])
|
753
|
+
return stats
|
754
|
+
def _summarizeKps(part='fullbody'):
|
755
|
+
stats = np.zeros((10,))
|
756
|
+
stats[0] = _summarize(1, maxDets=20, part=part)
|
757
|
+
stats[1] = _summarize(1, maxDets=20, iouThr=.5, part=part)
|
758
|
+
stats[2] = _summarize(1, maxDets=20, iouThr=.75, part=part)
|
759
|
+
stats[3] = _summarize(1, maxDets=20, areaRng='medium', part=part)
|
760
|
+
stats[4] = _summarize(1, maxDets=20, areaRng='large', part=part)
|
761
|
+
stats[5] = _summarize(0, maxDets=20, part=part)
|
762
|
+
stats[6] = _summarize(0, maxDets=20, iouThr=.5, part=part)
|
763
|
+
stats[7] = _summarize(0, maxDets=20, iouThr=.75, part=part)
|
764
|
+
stats[8] = _summarize(0, maxDets=20, areaRng='medium', part=part)
|
765
|
+
stats[9] = _summarize(0, maxDets=20, areaRng='large', part=part)
|
766
|
+
return {part: stats}
|
767
|
+
if not self.eval:
|
768
|
+
raise Exception('Please run accumulate() first')
|
769
|
+
iouType = self.params.iouType
|
770
|
+
if iouType == 'segm' or iouType == 'bbox':
|
771
|
+
summarize = _summarizeDets
|
772
|
+
self.stats = summarize()
|
773
|
+
elif iouType == 'keypoints':
|
774
|
+
summarize = _summarizeKps
|
775
|
+
parts = ['body', 'foot', 'face', 'hand', 'fullbody']
|
776
|
+
for part in parts:
|
777
|
+
print(part, ':')
|
778
|
+
self.stats.append(summarize(part))
|
779
|
+
|
780
|
+
def __str__(self):
|
781
|
+
self.summarize()
|
782
|
+
|
783
|
+
class Params:
|
784
|
+
'''
|
785
|
+
Params for coco evaluation api
|
786
|
+
'''
|
787
|
+
def setDetParams(self):
|
788
|
+
self.imgIds = []
|
789
|
+
self.catIds = []
|
790
|
+
# np.arange causes trouble. the data point on arange is slightly larger than the true value
|
791
|
+
self.iouThrs = np.linspace(.5, 0.95, int(np.round((0.95 - .5) / .05) + 1), endpoint=True)
|
792
|
+
self.recThrs = np.linspace(.0, 1.00, int(np.round((1.00 - .0) / .01) + 1), endpoint=True)
|
793
|
+
self.maxDets = [1, 10, 100]
|
794
|
+
self.areaRng = [[0 ** 2, 1e5 ** 2], [0 ** 2, 32 ** 2], [32 ** 2, 96 ** 2], [96 ** 2, 1e5 ** 2]]
|
795
|
+
self.areaRngLbl = ['all', 'small', 'medium', 'large']
|
796
|
+
self.useCats = 1
|
797
|
+
|
798
|
+
def setKpParams(self):
|
799
|
+
self.imgIds = []
|
800
|
+
self.catIds = []
|
801
|
+
# np.arange causes trouble. the data point on arange is slightly larger than the true value
|
802
|
+
self.iouThrs = np.linspace(.5, 0.95, int(np.round((0.95 - .5) / .05) + 1), endpoint=True)
|
803
|
+
self.recThrs = np.linspace(.0, 1.00, int(np.round((1.00 - .0) / .01) + 1), endpoint=True)
|
804
|
+
self.maxDets = [20]
|
805
|
+
self.areaRng = [[0 ** 2, 1e5 ** 2], [32 ** 2, 96 ** 2], [96 ** 2, 1e5 ** 2]]
|
806
|
+
self.areaRngLbl = ['all', 'medium', 'large']
|
807
|
+
self.useCats = 1
|
808
|
+
|
809
|
+
def __init__(self, iouType='segm'):
|
810
|
+
if iouType == 'segm' or iouType == 'bbox':
|
811
|
+
self.setDetParams()
|
812
|
+
elif iouType == 'keypoints':
|
813
|
+
self.setKpParams()
|
814
|
+
else:
|
815
|
+
raise Exception('iouType not supported')
|
816
|
+
self.iouType = iouType
|
817
|
+
# useSegm is deprecated
|
818
|
+
self.useSegm = None
|