原始代码

  1. __author__ = 'tsungyi'
  2. import numpy as np
  3. import datetime
  4. import time
  5. from collections import defaultdict
  6. from . import mask as maskUtils
  7. import copy
  8. class COCOeval:
  9. # Interface for evaluating detection on the Microsoft COCO dataset.
  10. #
  11. # The usage for CocoEval is as follows:
  12. # cocoGt=..., cocoDt=... # load dataset and results
  13. # E = CocoEval(cocoGt,cocoDt); # initialize CocoEval object
  14. # E.params.recThrs = ...; # set parameters as desired
  15. # E.evaluate(); # run per image evaluation
  16. # E.accumulate(); # accumulate per image results
  17. # E.summarize(); # display summary metrics of results
  18. # For example usage see evalDemo.m and http://mscoco.org/.
  19. #
  20. # The evaluation parameters are as follows (defaults in brackets):
  21. # imgIds - [all] N img ids to use for evaluation
  22. # catIds - [all] K cat ids to use for evaluation
  23. # iouThrs - [.5:.05:.95] T=10 IoU thresholds for evaluation
  24. # recThrs - [0:.01:1] R=101 recall thresholds for evaluation
  25. # areaRng - [...] A=4 object area ranges for evaluation
  26. # maxDets - [1 10 100] M=3 thresholds on max detections per image
  27. # iouType - ['segm'] set iouType to 'segm', 'bbox' or 'keypoints'
  28. # iouType replaced the now DEPRECATED useSegm parameter.
  29. # useCats - [1] if true use category labels for evaluation
  30. # Note: if useCats=0 category labels are ignored as in proposal scoring.
  31. # Note: multiple areaRngs [Ax2] and maxDets [Mx1] can be specified.
  32. #
  33. # evaluate(): evaluates detections on every image and every category and
  34. # concats the results into the "evalImgs" with fields:
  35. # dtIds - [1xD] id for each of the D detections (dt)
  36. # gtIds - [1xG] id for each of the G ground truths (gt)
  37. # dtMatches - [TxD] matching gt id at each IoU or 0
  38. # gtMatches - [TxG] matching dt id at each IoU or 0
  39. # dtScores - [1xD] confidence of each dt
  40. # gtIgnore - [1xG] ignore flag for each gt
  41. # dtIgnore - [TxD] ignore flag for each dt at each IoU
  42. #
  43. # accumulate(): accumulates the per-image, per-category evaluation
  44. # results in "evalImgs" into the dictionary "eval" with fields:
  45. # params - parameters used for evaluation
  46. # date - date evaluation was performed
  47. # counts - [T,R,K,A,M] parameter dimensions (see above)
  48. # precision - [TxRxKxAxM] precision for every evaluation setting
  49. # recall - [TxKxAxM] max recall for every evaluation setting
  50. # Note: precision and recall==-1 for settings with no gt objects.
  51. #
  52. # See also coco, mask, pycocoDemo, pycocoEvalDemo
  53. #
  54. # Microsoft COCO Toolbox. version 2.0
  55. # Data, paper, and tutorials available at: http://mscoco.org/
  56. # Code written by Piotr Dollar and Tsung-Yi Lin, 2015.
  57. # Licensed under the Simplified BSD License [see coco/license.txt]
  58. def __init__(self, cocoGt=None, cocoDt=None, iouType='segm'):
  59. '''
  60. Initialize CocoEval using coco APIs for gt and dt
  61. :param cocoGt: coco object with ground truth annotations
  62. :param cocoDt: coco object with detection results
  63. :return: None
  64. '''
  65. if not iouType:
  66. print('iouType not specified. use default iouType segm')
  67. self.cocoGt = cocoGt # ground truth COCO API
  68. self.cocoDt = cocoDt # detections COCO API
  69. self.evalImgs = defaultdict(list) # per-image per-category evaluation results [KxAxI] elements
  70. self.eval = {} # accumulated evaluation results
  71. self._gts = defaultdict(list) # gt for evaluation
  72. self._dts = defaultdict(list) # dt for evaluation
  73. self.params = Params(iouType=iouType) # parameters
  74. self._paramsEval = {} # parameters for evaluation
  75. self.stats = [] # result summarization
  76. self.ious = {} # ious between all gts and dts
  77. if not cocoGt is None:
  78. self.params.imgIds = sorted(cocoGt.getImgIds())
  79. self.params.catIds = sorted(cocoGt.getCatIds())
  80. def _prepare(self):
  81. '''
  82. Prepare ._gts and ._dts for evaluation based on params
  83. :return: None
  84. '''
  85. def _toMask(anns, coco):
  86. # modify ann['segmentation'] by reference
  87. for ann in anns:
  88. rle = coco.annToRLE(ann)
  89. ann['segmentation'] = rle
  90. p = self.params
  91. if p.useCats:
  92. gts=self.cocoGt.loadAnns(self.cocoGt.getAnnIds(imgIds=p.imgIds, catIds=p.catIds))
  93. dts=self.cocoDt.loadAnns(self.cocoDt.getAnnIds(imgIds=p.imgIds, catIds=p.catIds))
  94. else:
  95. gts=self.cocoGt.loadAnns(self.cocoGt.getAnnIds(imgIds=p.imgIds))
  96. dts=self.cocoDt.loadAnns(self.cocoDt.getAnnIds(imgIds=p.imgIds))
  97. # convert ground truth to mask if iouType == 'segm'
  98. if p.iouType == 'segm':
  99. _toMask(gts, self.cocoGt)
  100. _toMask(dts, self.cocoDt)
  101. # set ignore flag
  102. for gt in gts:
  103. gt['ignore'] = gt['ignore'] if 'ignore' in gt else 0
  104. gt['ignore'] = 'iscrowd' in gt and gt['iscrowd']
  105. if p.iouType == 'keypoints':
  106. gt['ignore'] = (gt['num_keypoints'] == 0) or gt['ignore']
  107. self._gts = defaultdict(list) # gt for evaluation
  108. self._dts = defaultdict(list) # dt for evaluation
  109. for gt in gts:
  110. self._gts[gt['image_id'], gt['category_id']].append(gt)
  111. for dt in dts:
  112. self._dts[dt['image_id'], dt['category_id']].append(dt)
  113. self.evalImgs = defaultdict(list) # per-image per-category evaluation results
  114. self.eval = {} # accumulated evaluation results
  115. def evaluate(self):
  116. '''
  117. Run per image evaluation on given images and store results (a list of dict) in self.evalImgs
  118. :return: None
  119. '''
  120. tic = time.time()
  121. print('Running per image evaluation...')
  122. p = self.params
  123. # add backward compatibility if useSegm is specified in params
  124. if not p.useSegm is None:
  125. p.iouType = 'segm' if p.useSegm == 1 else 'bbox'
  126. print('useSegm (deprecated) is not None. Running {} evaluation'.format(p.iouType))
  127. print('Evaluate annotation type *{}*'.format(p.iouType))
  128. p.imgIds = list(np.unique(p.imgIds))
  129. if p.useCats:
  130. p.catIds = list(np.unique(p.catIds))
  131. p.maxDets = sorted(p.maxDets)
  132. self.params=p
  133. self._prepare()
  134. # loop through images, area range, max detection number
  135. catIds = p.catIds if p.useCats else [-1]
  136. if p.iouType == 'segm' or p.iouType == 'bbox':
  137. computeIoU = self.computeIoU
  138. elif p.iouType == 'keypoints':
  139. computeIoU = self.computeOks
  140. self.ious = {(imgId, catId): computeIoU(imgId, catId) \
  141. for imgId in p.imgIds
  142. for catId in catIds}
  143. evaluateImg = self.evaluateImg
  144. maxDet = p.maxDets[-1]
  145. self.evalImgs = [evaluateImg(imgId, catId, areaRng, maxDet)
  146. for catId in catIds
  147. for areaRng in p.areaRng
  148. for imgId in p.imgIds
  149. ]
  150. self._paramsEval = copy.deepcopy(self.params)
  151. toc = time.time()
  152. print('DONE (t={:0.2f}s).'.format(toc-tic))
  153. def computeIoU(self, imgId, catId):
  154. p = self.params
  155. if p.useCats:
  156. gt = self._gts[imgId,catId]
  157. dt = self._dts[imgId,catId]
  158. else:
  159. gt = [_ for cId in p.catIds for _ in self._gts[imgId,cId]]
  160. dt = [_ for cId in p.catIds for _ in self._dts[imgId,cId]]
  161. if len(gt) == 0 and len(dt) ==0:
  162. return []
  163. inds = np.argsort([-d['score'] for d in dt], kind='mergesort')
  164. dt = [dt[i] for i in inds]
  165. if len(dt) > p.maxDets[-1]:
  166. dt=dt[0:p.maxDets[-1]]
  167. if p.iouType == 'segm':
  168. g = [g['segmentation'] for g in gt]
  169. d = [d['segmentation'] for d in dt]
  170. elif p.iouType == 'bbox':
  171. g = [g['bbox'] for g in gt]
  172. d = [d['bbox'] for d in dt]
  173. else:
  174. raise Exception('unknown iouType for iou computation')
  175. # compute iou between each dt and gt region
  176. iscrowd = [int(o['iscrowd']) for o in gt]
  177. ious = maskUtils.iou(d,g,iscrowd)
  178. return ious
  179. def computeOks(self, imgId, catId):
  180. p = self.params
  181. # dimention here should be Nxm
  182. gts = self._gts[imgId, catId]
  183. dts = self._dts[imgId, catId]
  184. inds = np.argsort([-d['score'] for d in dts], kind='mergesort')
  185. dts = [dts[i] for i in inds]
  186. if len(dts) > p.maxDets[-1]:
  187. dts = dts[0:p.maxDets[-1]]
  188. # if len(gts) == 0 and len(dts) == 0:
  189. if len(gts) == 0 or len(dts) == 0:
  190. return []
  191. ious = np.zeros((len(dts), len(gts)))
  192. sigmas = p.kpt_oks_sigmas
  193. vars = (sigmas * 2)**2
  194. k = len(sigmas)
  195. # compute oks between each detection and ground truth object
  196. for j, gt in enumerate(gts):
  197. # create bounds for ignore regions(double the gt bbox)
  198. g = np.array(gt['keypoints'])
  199. xg = g[0::3]; yg = g[1::3]; vg = g[2::3]
  200. k1 = np.count_nonzero(vg > 0)
  201. bb = gt['bbox']
  202. x0 = bb[0] - bb[2]; x1 = bb[0] + bb[2] * 2
  203. y0 = bb[1] - bb[3]; y1 = bb[1] + bb[3] * 2
  204. for i, dt in enumerate(dts):
  205. d = np.array(dt['keypoints'])
  206. xd = d[0::3]; yd = d[1::3]
  207. if k1>0:
  208. # measure the per-keypoint distance if keypoints visible
  209. dx = xd - xg
  210. dy = yd - yg
  211. else:
  212. # measure minimum distance to keypoints in (x0,y0) & (x1,y1)
  213. z = np.zeros((k))
  214. dx = np.max((z, x0-xd),axis=0)+np.max((z, xd-x1),axis=0)
  215. dy = np.max((z, y0-yd),axis=0)+np.max((z, yd-y1),axis=0)
  216. e = (dx**2 + dy**2) / vars / (gt['area']+np.spacing(1)) / 2
  217. if k1 > 0:
  218. e=e[vg > 0]
  219. ious[i, j] = np.sum(np.exp(-e)) / e.shape[0]
  220. return ious
  221. def evaluateImg(self, imgId, catId, aRng, maxDet):
  222. '''
  223. perform evaluation for single category and image
  224. :return: dict (single image results)
  225. '''
  226. p = self.params
  227. if p.useCats:
  228. gt = self._gts[imgId,catId]
  229. dt = self._dts[imgId,catId]
  230. else:
  231. gt = [_ for cId in p.catIds for _ in self._gts[imgId,cId]]
  232. dt = [_ for cId in p.catIds for _ in self._dts[imgId,cId]]
  233. if len(gt) == 0 and len(dt) ==0:
  234. return None
  235. for g in gt:
  236. if g['ignore'] or (g['area']<aRng[0] or g['area']>aRng[1]):
  237. g['_ignore'] = 1
  238. else:
  239. g['_ignore'] = 0
  240. # sort dt highest score first, sort gt ignore last
  241. gtind = np.argsort([g['_ignore'] for g in gt], kind='mergesort')
  242. gt = [gt[i] for i in gtind]
  243. dtind = np.argsort([-d['score'] for d in dt], kind='mergesort')
  244. dt = [dt[i] for i in dtind[0:maxDet]]
  245. iscrowd = [int(o['iscrowd']) for o in gt]
  246. # load computed ious
  247. ious = self.ious[imgId, catId][:, gtind] if len(self.ious[imgId, catId]) > 0 else self.ious[imgId, catId]
  248. T = len(p.iouThrs)
  249. G = len(gt)
  250. D = len(dt)
  251. gtm = np.zeros((T,G))
  252. dtm = np.zeros((T,D))
  253. gtIg = np.array([g['_ignore'] for g in gt])
  254. dtIg = np.zeros((T,D))
  255. if not len(ious)==0:
  256. for tind, t in enumerate(p.iouThrs):
  257. for dind, d in enumerate(dt):
  258. # information about best match so far (m=-1 -> unmatched)
  259. iou = min([t,1-1e-10])
  260. m = -1
  261. for gind, g in enumerate(gt):
  262. # if this gt already matched, and not a crowd, continue
  263. if gtm[tind,gind]>0 and not iscrowd[gind]:
  264. continue
  265. # if dt matched to reg gt, and on ignore gt, stop
  266. if m>-1 and gtIg[m]==0 and gtIg[gind]==1:
  267. break
  268. # continue to next gt unless better match made
  269. if ious[dind,gind] < iou:
  270. continue
  271. # if match successful and best so far, store appropriately
  272. iou=ious[dind,gind]
  273. m=gind
  274. # if match made store id of match for both dt and gt
  275. if m ==-1:
  276. continue
  277. dtIg[tind,dind] = gtIg[m]
  278. dtm[tind,dind] = gt[m]['id']
  279. gtm[tind,m] = d['id']
  280. # set unmatched detections outside of area range to ignore
  281. a = np.array([d['area']<aRng[0] or d['area']>aRng[1] for d in dt]).reshape((1, len(dt)))
  282. dtIg = np.logical_or(dtIg, np.logical_and(dtm==0, np.repeat(a,T,0)))
  283. # store results for given image and category
  284. return {
  285. 'image_id': imgId,
  286. 'category_id': catId,
  287. 'aRng': aRng,
  288. 'maxDet': maxDet,
  289. 'dtIds': [d['id'] for d in dt],
  290. 'gtIds': [g['id'] for g in gt],
  291. 'dtMatches': dtm,
  292. 'gtMatches': gtm,
  293. 'dtScores': [d['score'] for d in dt],
  294. 'gtIgnore': gtIg,
  295. 'dtIgnore': dtIg,
  296. }
  297. def accumulate(self, p = None):
  298. '''
  299. Accumulate per image evaluation results and store the result in self.eval
  300. :param p: input params for evaluation
  301. :return: None
  302. '''
  303. print('Accumulating evaluation results...')
  304. tic = time.time()
  305. if not self.evalImgs:
  306. print('Please run evaluate() first')
  307. # allows input customized parameters
  308. if p is None:
  309. p = self.params
  310. p.catIds = p.catIds if p.useCats == 1 else [-1]
  311. T = len(p.iouThrs)
  312. R = len(p.recThrs)
  313. K = len(p.catIds) if p.useCats else 1
  314. A = len(p.areaRng)
  315. M = len(p.maxDets)
  316. precision = -np.ones((T,R,K,A,M)) # -1 for the precision of absent categories
  317. recall = -np.ones((T,K,A,M))
  318. scores = -np.ones((T,R,K,A,M))
  319. # create dictionary for future indexing
  320. _pe = self._paramsEval
  321. catIds = _pe.catIds if _pe.useCats else [-1]
  322. setK = set(catIds)
  323. setA = set(map(tuple, _pe.areaRng))
  324. setM = set(_pe.maxDets)
  325. setI = set(_pe.imgIds)
  326. # get inds to evaluate
  327. k_list = [n for n, k in enumerate(p.catIds) if k in setK]
  328. m_list = [m for n, m in enumerate(p.maxDets) if m in setM]
  329. a_list = [n for n, a in enumerate(map(lambda x: tuple(x), p.areaRng)) if a in setA]
  330. i_list = [n for n, i in enumerate(p.imgIds) if i in setI]
  331. I0 = len(_pe.imgIds)
  332. A0 = len(_pe.areaRng)
  333. # retrieve E at each category, area range, and max number of detections
  334. for k, k0 in enumerate(k_list):
  335. Nk = k0*A0*I0
  336. for a, a0 in enumerate(a_list):
  337. Na = a0*I0
  338. for m, maxDet in enumerate(m_list):
  339. E = [self.evalImgs[Nk + Na + i] for i in i_list]
  340. E = [e for e in E if not e is None]
  341. if len(E) == 0:
  342. continue
  343. dtScores = np.concatenate([e['dtScores'][0:maxDet] for e in E])
  344. # different sorting method generates slightly different results.
  345. # mergesort is used to be consistent as Matlab implementation.
  346. inds = np.argsort(-dtScores, kind='mergesort')
  347. dtScoresSorted = dtScores[inds]
  348. dtm = np.concatenate([e['dtMatches'][:,0:maxDet] for e in E], axis=1)[:,inds]
  349. dtIg = np.concatenate([e['dtIgnore'][:,0:maxDet] for e in E], axis=1)[:,inds]
  350. gtIg = np.concatenate([e['gtIgnore'] for e in E])
  351. npig = np.count_nonzero(gtIg==0 )
  352. if npig == 0:
  353. continue
  354. tps = np.logical_and( dtm, np.logical_not(dtIg) )
  355. fps = np.logical_and(np.logical_not(dtm), np.logical_not(dtIg) )
  356. tp_sum = np.cumsum(tps, axis=1).astype(dtype=np.float)
  357. fp_sum = np.cumsum(fps, axis=1).astype(dtype=np.float)
  358. for t, (tp, fp) in enumerate(zip(tp_sum, fp_sum)):
  359. tp = np.array(tp)
  360. fp = np.array(fp)
  361. nd = len(tp)
  362. rc = tp / npig
  363. pr = tp / (fp+tp+np.spacing(1))
  364. q = np.zeros((R,))
  365. ss = np.zeros((R,))
  366. if nd:
  367. recall[t,k,a,m] = rc[-1]
  368. else:
  369. recall[t,k,a,m] = 0
  370. # numpy is slow without cython optimization for accessing elements
  371. # use python array gets significant speed improvement
  372. pr = pr.tolist(); q = q.tolist()
  373. for i in range(nd-1, 0, -1):
  374. if pr[i] > pr[i-1]:
  375. pr[i-1] = pr[i]
  376. inds = np.searchsorted(rc, p.recThrs, side='left')
  377. try:
  378. for ri, pi in enumerate(inds):
  379. q[ri] = pr[pi]
  380. ss[ri] = dtScoresSorted[pi]
  381. except:
  382. pass
  383. precision[t,:,k,a,m] = np.array(q)
  384. scores[t,:,k,a,m] = np.array(ss)
  385. self.eval = {
  386. 'params': p,
  387. 'counts': [T, R, K, A, M],
  388. 'date': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  389. 'precision': precision,
  390. 'recall': recall,
  391. 'scores': scores,
  392. }
  393. toc = time.time()
  394. print('DONE (t={:0.2f}s).'.format( toc-tic))
  395. def summarize(self):
  396. '''
  397. Compute and display summary metrics for evaluation results.
  398. Note this functin can *only* be applied on the default parameter setting
  399. '''
  400. def _summarize( ap=1, iouThr=None, areaRng='all', maxDets=100 ):
  401. p = self.params
  402. iStr = ' {:<18} {} @[ IoU={:<9} | area={:>6s} | maxDets={:>3d} ] = {:0.3f}'
  403. titleStr = 'Average Precision' if ap == 1 else 'Average Recall'
  404. typeStr = '(AP)' if ap==1 else '(AR)'
  405. iouStr = '{:0.2f}:{:0.2f}'.format(p.iouThrs[0], p.iouThrs[-1]) \
  406. if iouThr is None else '{:0.2f}'.format(iouThr)
  407. aind = [i for i, aRng in enumerate(p.areaRngLbl) if aRng == areaRng]
  408. mind = [i for i, mDet in enumerate(p.maxDets) if mDet == maxDets]
  409. if ap == 1:
  410. # dimension of precision: [TxRxKxAxM]
  411. s = self.eval['precision']
  412. # IoU
  413. if iouThr is not None:
  414. t = np.where(iouThr == p.iouThrs)[0]
  415. s = s[t]
  416. s = s[:,:,:,aind,mind]
  417. else:
  418. # dimension of recall: [TxKxAxM]
  419. s = self.eval['recall']
  420. if iouThr is not None:
  421. t = np.where(iouThr == p.iouThrs)[0]
  422. s = s[t]
  423. s = s[:,:,aind,mind]
  424. if len(s[s>-1])==0:
  425. mean_s = -1
  426. else:
  427. mean_s = np.mean(s[s>-1])
  428. print(iStr.format(titleStr, typeStr, iouStr, areaRng, maxDets, mean_s))
  429. return mean_s
  430. def _summarizeDets():
  431. stats = np.zeros((12,))
  432. stats[0] = _summarize(1)
  433. stats[1] = _summarize(1, iouThr=.5, maxDets=self.params.maxDets[2])
  434. stats[2] = _summarize(1, iouThr=.75, maxDets=self.params.maxDets[2])
  435. stats[3] = _summarize(1, areaRng='small', maxDets=self.params.maxDets[2])
  436. stats[4] = _summarize(1, areaRng='medium', maxDets=self.params.maxDets[2])
  437. stats[5] = _summarize(1, areaRng='large', maxDets=self.params.maxDets[2])
  438. stats[6] = _summarize(0, maxDets=self.params.maxDets[0])
  439. stats[7] = _summarize(0, maxDets=self.params.maxDets[1])
  440. stats[8] = _summarize(0, maxDets=self.params.maxDets[2])
  441. stats[9] = _summarize(0, areaRng='small', maxDets=self.params.maxDets[2])
  442. stats[10] = _summarize(0, areaRng='medium', maxDets=self.params.maxDets[2])
  443. stats[11] = _summarize(0, areaRng='large', maxDets=self.params.maxDets[2])
  444. return stats
  445. def _summarizeKps():
  446. stats = np.zeros((10,))
  447. stats[0] = _summarize(1, maxDets=20)
  448. stats[1] = _summarize(1, maxDets=20, iouThr=.5)
  449. stats[2] = _summarize(1, maxDets=20, iouThr=.75)
  450. stats[3] = _summarize(1, maxDets=20, areaRng='medium')
  451. stats[4] = _summarize(1, maxDets=20, areaRng='large')
  452. stats[5] = _summarize(0, maxDets=20)
  453. stats[6] = _summarize(0, maxDets=20, iouThr=.5)
  454. stats[7] = _summarize(0, maxDets=20, iouThr=.75)
  455. stats[8] = _summarize(0, maxDets=20, areaRng='medium')
  456. stats[9] = _summarize(0, maxDets=20, areaRng='large')
  457. return stats
  458. if not self.eval:
  459. raise Exception('Please run accumulate() first')
  460. iouType = self.params.iouType
  461. if iouType == 'segm' or iouType == 'bbox':
  462. summarize = _summarizeDets
  463. elif iouType == 'keypoints':
  464. summarize = _summarizeKps
  465. self.stats = summarize()
  466. def __str__(self):
  467. self.summarize()
  468. class Params:
  469. '''
  470. Params for coco evaluation api
  471. '''
  472. def setDetParams(self):
  473. self.imgIds = []
  474. self.catIds = []
  475. # np.arange causes trouble. the data point on arange is slightly larger than the true value
  476. self.iouThrs = np.linspace(.5, 0.95, int(np.round((0.95 - .5) / .05)) + 1, endpoint=True)
  477. self.recThrs = np.linspace(.0, 1.00, int(np.round((1.00 - .0) / .01)) + 1, endpoint=True)
  478. self.maxDets = [1, 10, 100]
  479. self.areaRng = [[0 ** 2, 1e5 ** 2], [0 ** 2, 32 ** 2], [32 ** 2, 96 ** 2], [96 ** 2, 1e5 ** 2]]
  480. self.areaRngLbl = ['all', 'small', 'medium', 'large']
  481. self.useCats = 1
  482. def setKpParams(self):
  483. self.imgIds = []
  484. self.catIds = []
  485. # np.arange causes trouble. the data point on arange is slightly larger than the true value
  486. self.iouThrs = np.linspace(.5, 0.95, int(np.round((0.95 - .5) / .05)) + 1, endpoint=True)
  487. self.recThrs = np.linspace(.0, 1.00, int(np.round((1.00 - .0) / .01)) + 1, endpoint=True)
  488. self.maxDets = [20]
  489. self.areaRng = [[0 ** 2, 1e5 ** 2], [32 ** 2, 96 ** 2], [96 ** 2, 1e5 ** 2]]
  490. self.areaRngLbl = ['all', 'medium', 'large']
  491. self.useCats = 1
  492. self.kpt_oks_sigmas = np.array([.26, .25, .25, .35, .35, .79, .79, .72, .72, .62,.62, 1.07, 1.07, .87, .87, .89, .89])/10.0
  493. def __init__(self, iouType='segm'):
  494. if iouType == 'segm' or iouType == 'bbox':
  495. self.setDetParams()
  496. elif iouType == 'keypoints':
  497. self.setKpParams()
  498. else:
  499. raise Exception('iouType not supported')
  500. self.iouType = iouType
  501. # useSegm is deprecated
  502. self.useSegm = None

优化cocoeval.py代码

优化其中的代码是为了画随着ap随着iou变化的plot图片。

  1. __author__ = 'tsungyi'
  2. import numpy as np
  3. import datetime
  4. import time
  5. from collections import defaultdict
  6. from . import mask as maskUtils
  7. import copy
  8. class COCOeval:
  9. # Interface for evaluating detection on the Microsoft COCO dataset.
  10. #
  11. # The usage for CocoEval is as follows:
  12. # cocoGt=..., cocoDt=... # load dataset and results
  13. # E = CocoEval(cocoGt,cocoDt); # initialize CocoEval object
  14. # E.params.recThrs = ...; # set parameters as desired
  15. # E.evaluate(); # run per image evaluation
  16. # E.accumulate(); # accumulate per image results
  17. # E.summarize(); # display summary metrics of results
  18. # For example usage see evalDemo.m and http://mscoco.org/.
  19. #
  20. # The evaluation parameters are as follows (defaults in brackets):
  21. # imgIds - [all] N img ids to use for evaluation
  22. # catIds - [all] K cat ids to use for evaluation
  23. # iouThrs - [.5:.05:.95] T=10 IoU thresholds for evaluation
  24. # recThrs - [0:.01:1] R=101 recall thresholds for evaluation
  25. # areaRng - [...] A=4 object area ranges for evaluation
  26. # maxDets - [1 10 100] M=3 thresholds on max detections per image
  27. # iouType - ['segm'] set iouType to 'segm', 'bbox' or 'keypoints'
  28. # iouType replaced the now DEPRECATED useSegm parameter.
  29. # useCats - [1] if true use category labels for evaluation
  30. # Note: if useCats=0 category labels are ignored as in proposal scoring.
  31. # Note: multiple areaRngs [Ax2] and maxDets [Mx1] can be specified.
  32. #
  33. # evaluate(): evaluates detections on every image and every category and
  34. # concats the results into the "evalImgs" with fields:
  35. # dtIds - [1xD] id for each of the D detections (dt)
  36. # gtIds - [1xG] id for each of the G ground truths (gt)
  37. # dtMatches - [TxD] matching gt id at each IoU or 0
  38. # gtMatches - [TxG] matching dt id at each IoU or 0
  39. # dtScores - [1xD] confidence of each dt
  40. # gtIgnore - [1xG] ignore flag for each gt
  41. # dtIgnore - [TxD] ignore flag for each dt at each IoU
  42. #
  43. # accumulate(): accumulates the per-image, per-category evaluation
  44. # results in "evalImgs" into the dictionary "eval" with fields:
  45. # params - parameters used for evaluation
  46. # date - date evaluation was performed
  47. # counts - [T,R,K,A,M] parameter dimensions (see above)
  48. # precision - [TxRxKxAxM] precision for every evaluation setting
  49. # recall - [TxKxAxM] max recall for every evaluation setting
  50. # Note: precision and recall==-1 for settings with no gt objects.
  51. #
  52. # See also coco, mask, pycocoDemo, pycocoEvalDemo
  53. #
  54. # Microsoft COCO Toolbox. version 2.0
  55. # Data, paper, and tutorials available at: http://mscoco.org/
  56. # Code written by Piotr Dollar and Tsung-Yi Lin, 2015.
  57. # Licensed under the Simplified BSD License [see coco/license.txt]
  58. def __init__(self, cocoGt=None, cocoDt=None, iouType='segm'):
  59. '''
  60. Initialize CocoEval using coco APIs for gt and dt
  61. :param cocoGt: coco object with ground truth annotations
  62. :param cocoDt: coco object with detection results
  63. :return: None
  64. '''
  65. if not iouType:
  66. print('iouType not specified. use default iouType segm')
  67. self.cocoGt = cocoGt # ground truth COCO API
  68. self.cocoDt = cocoDt # detections COCO API
  69. # per-image per-category evaluation results [KxAxI] elements
  70. self.evalImgs = defaultdict(list)
  71. self.eval = {} # accumulated evaluation results
  72. self._gts = defaultdict(list) # gt for evaluation
  73. self._dts = defaultdict(list) # dt for evaluation
  74. self.params = Params(iouType=iouType) # parameters
  75. self._paramsEval = {} # parameters for evaluation
  76. self.stats = [] # result summarization
  77. self.ious = {} # ious between all gts and dts
  78. if not cocoGt is None:
  79. self.params.imgIds = sorted(cocoGt.getImgIds())
  80. self.params.catIds = sorted(cocoGt.getCatIds())
  81. def _prepare(self):
  82. '''
  83. Prepare ._gts and ._dts for evaluation based on params
  84. :return: None
  85. '''
  86. def _toMask(anns, coco):
  87. # modify ann['segmentation'] by reference
  88. for ann in anns:
  89. rle = coco.annToRLE(ann)
  90. ann['segmentation'] = rle
  91. p = self.params
  92. if p.useCats:
  93. gts = self.cocoGt.loadAnns(self.cocoGt.getAnnIds(
  94. imgIds=p.imgIds, catIds=p.catIds))
  95. dts = self.cocoDt.loadAnns(self.cocoDt.getAnnIds(
  96. imgIds=p.imgIds, catIds=p.catIds))
  97. else:
  98. gts = self.cocoGt.loadAnns(self.cocoGt.getAnnIds(imgIds=p.imgIds))
  99. dts = self.cocoDt.loadAnns(self.cocoDt.getAnnIds(imgIds=p.imgIds))
  100. # convert ground truth to mask if iouType == 'segm'
  101. if p.iouType == 'segm':
  102. _toMask(gts, self.cocoGt)
  103. _toMask(dts, self.cocoDt)
  104. # set ignore flag
  105. for gt in gts:
  106. gt['ignore'] = gt['ignore'] if 'ignore' in gt else 0
  107. gt['ignore'] = 'iscrowd' in gt and gt['iscrowd']
  108. if p.iouType == 'keypoints':
  109. gt['ignore'] = (gt['num_keypoints'] == 0) or gt['ignore']
  110. self._gts = defaultdict(list) # gt for evaluation
  111. self._dts = defaultdict(list) # dt for evaluation
  112. for gt in gts:
  113. self._gts[gt['image_id'], gt['category_id']].append(gt)
  114. for dt in dts:
  115. self._dts[dt['image_id'], dt['category_id']].append(dt)
  116. # per-image per-category evaluation results
  117. self.evalImgs = defaultdict(list)
  118. self.eval = {} # accumulated evaluation results
  119. def evaluate(self):
  120. '''
  121. Run per image evaluation on given images and store results (a list of dict) in self.evalImgs
  122. :return: None
  123. '''
  124. tic = time.time()
  125. print('Running per image evaluation...')
  126. p = self.params
  127. # add backward compatibility if useSegm is specified in params
  128. if not p.useSegm is None:
  129. p.iouType = 'segm' if p.useSegm == 1 else 'bbox'
  130. print(
  131. 'useSegm (deprecated) is not None. Running {} evaluation'.format(p.iouType))
  132. print('Evaluate annotation type *{}*'.format(p.iouType))
  133. p.imgIds = list(np.unique(p.imgIds))
  134. if p.useCats:
  135. p.catIds = list(np.unique(p.catIds))
  136. p.maxDets = sorted(p.maxDets)
  137. self.params = p
  138. self._prepare()
  139. # loop through images, area range, max detection number
  140. catIds = p.catIds if p.useCats else [-1]
  141. if p.iouType == 'segm' or p.iouType == 'bbox':
  142. computeIoU = self.computeIoU
  143. elif p.iouType == 'keypoints':
  144. computeIoU = self.computeOks
  145. self.ious = {(imgId, catId): computeIoU(imgId, catId)
  146. for imgId in p.imgIds
  147. for catId in catIds}
  148. evaluateImg = self.evaluateImg
  149. maxDet = p.maxDets[-1]
  150. self.evalImgs = [evaluateImg(imgId, catId, areaRng, maxDet)
  151. for catId in catIds
  152. for areaRng in p.areaRng
  153. for imgId in p.imgIds
  154. ]
  155. self._paramsEval = copy.deepcopy(self.params)
  156. toc = time.time()
  157. print('DONE (t={:0.2f}s).'.format(toc-tic))
  158. def computeIoU(self, imgId, catId):
  159. p = self.params
  160. if p.useCats:
  161. gt = self._gts[imgId, catId]
  162. dt = self._dts[imgId, catId]
  163. else:
  164. gt = [_ for cId in p.catIds for _ in self._gts[imgId, cId]]
  165. dt = [_ for cId in p.catIds for _ in self._dts[imgId, cId]]
  166. if len(gt) == 0 and len(dt) == 0:
  167. return []
  168. inds = np.argsort([-d['score'] for d in dt], kind='mergesort')
  169. dt = [dt[i] for i in inds]
  170. if len(dt) > p.maxDets[-1]:
  171. dt = dt[0:p.maxDets[-1]]
  172. if p.iouType == 'segm':
  173. g = [g['segmentation'] for g in gt]
  174. d = [d['segmentation'] for d in dt]
  175. elif p.iouType == 'bbox':
  176. g = [g['bbox'] for g in gt]
  177. d = [d['bbox'] for d in dt]
  178. else:
  179. raise Exception('unknown iouType for iou computation')
  180. # compute iou between each dt and gt region
  181. iscrowd = [int(o['iscrowd']) for o in gt]
  182. ious = maskUtils.iou(d, g, iscrowd)
  183. return ious
  184. def computeOks(self, imgId, catId):
  185. p = self.params
  186. # dimention here should be Nxm
  187. gts = self._gts[imgId, catId]
  188. dts = self._dts[imgId, catId]
  189. inds = np.argsort([-d['score'] for d in dts], kind='mergesort')
  190. dts = [dts[i] for i in inds]
  191. if len(dts) > p.maxDets[-1]:
  192. dts = dts[0:p.maxDets[-1]]
  193. # if len(gts) == 0 and len(dts) == 0:
  194. if len(gts) == 0 or len(dts) == 0:
  195. return []
  196. ious = np.zeros((len(dts), len(gts)))
  197. sigmas = p.kpt_oks_sigmas
  198. vars = (sigmas * 2)**2
  199. k = len(sigmas)
  200. # compute oks between each detection and ground truth object
  201. for j, gt in enumerate(gts):
  202. # create bounds for ignore regions(double the gt bbox)
  203. g = np.array(gt['keypoints'])
  204. xg = g[0::3]
  205. yg = g[1::3]
  206. vg = g[2::3]
  207. k1 = np.count_nonzero(vg > 0)
  208. bb = gt['bbox']
  209. x0 = bb[0] - bb[2]
  210. x1 = bb[0] + bb[2] * 2
  211. y0 = bb[1] - bb[3]
  212. y1 = bb[1] + bb[3] * 2
  213. for i, dt in enumerate(dts):
  214. d = np.array(dt['keypoints'])
  215. xd = d[0::3]
  216. yd = d[1::3]
  217. if k1 > 0:
  218. # measure the per-keypoint distance if keypoints visible
  219. dx = xd - xg
  220. dy = yd - yg
  221. else:
  222. # measure minimum distance to keypoints in (x0,y0) & (x1,y1)
  223. z = np.zeros((k))
  224. dx = np.max((z, x0-xd), axis=0)+np.max((z, xd-x1), axis=0)
  225. dy = np.max((z, y0-yd), axis=0)+np.max((z, yd-y1), axis=0)
  226. e = (dx**2 + dy**2) / vars / (gt['area']+np.spacing(1)) / 2
  227. if k1 > 0:
  228. e = e[vg > 0]
  229. ious[i, j] = np.sum(np.exp(-e)) / e.shape[0]
  230. return ious
  231. def evaluateImg(self, imgId, catId, aRng, maxDet):
  232. '''
  233. perform evaluation for single category and image
  234. :return: dict (single image results)
  235. '''
  236. p = self.params
  237. if p.useCats:
  238. gt = self._gts[imgId, catId]
  239. dt = self._dts[imgId, catId]
  240. else:
  241. gt = [_ for cId in p.catIds for _ in self._gts[imgId, cId]]
  242. dt = [_ for cId in p.catIds for _ in self._dts[imgId, cId]]
  243. if len(gt) == 0 and len(dt) == 0:
  244. return None
  245. for g in gt:
  246. if g['ignore'] or (g['area'] < aRng[0] or g['area'] > aRng[1]):
  247. g['_ignore'] = 1
  248. else:
  249. g['_ignore'] = 0
  250. # sort dt highest score first, sort gt ignore last
  251. gtind = np.argsort([g['_ignore'] for g in gt], kind='mergesort')
  252. gt = [gt[i] for i in gtind]
  253. dtind = np.argsort([-d['score'] for d in dt], kind='mergesort')
  254. dt = [dt[i] for i in dtind[0:maxDet]]
  255. iscrowd = [int(o['iscrowd']) for o in gt]
  256. # load computed ious
  257. ious = self.ious[imgId, catId][:, gtind] if len(
  258. self.ious[imgId, catId]) > 0 else self.ious[imgId, catId]
  259. T = len(p.iouThrs)
  260. G = len(gt)
  261. D = len(dt)
  262. gtm = np.zeros((T, G))
  263. dtm = np.zeros((T, D))
  264. gtIg = np.array([g['_ignore'] for g in gt])
  265. dtIg = np.zeros((T, D))
  266. if not len(ious) == 0:
  267. for tind, t in enumerate(p.iouThrs):
  268. for dind, d in enumerate(dt):
  269. # information about best match so far (m=-1 -> unmatched)
  270. iou = min([t, 1-1e-10])
  271. m = -1
  272. for gind, g in enumerate(gt):
  273. # if this gt already matched, and not a crowd, continue
  274. if gtm[tind, gind] > 0 and not iscrowd[gind]:
  275. continue
  276. # if dt matched to reg gt, and on ignore gt, stop
  277. if m > -1 and gtIg[m] == 0 and gtIg[gind] == 1:
  278. break
  279. # continue to next gt unless better match made
  280. if ious[dind, gind] < iou:
  281. continue
  282. # if match successful and best so far, store appropriately
  283. iou = ious[dind, gind]
  284. m = gind
  285. # if match made store id of match for both dt and gt
  286. if m == -1:
  287. continue
  288. dtIg[tind, dind] = gtIg[m]
  289. dtm[tind, dind] = gt[m]['id']
  290. gtm[tind, m] = d['id']
  291. # set unmatched detections outside of area range to ignore
  292. a = np.array([d['area'] < aRng[0] or d['area'] > aRng[1]
  293. for d in dt]).reshape((1, len(dt)))
  294. dtIg = np.logical_or(dtIg, np.logical_and(
  295. dtm == 0, np.repeat(a, T, 0)))
  296. # store results for given image and category
  297. return {
  298. 'image_id': imgId,
  299. 'category_id': catId,
  300. 'aRng': aRng,
  301. 'maxDet': maxDet,
  302. 'dtIds': [d['id'] for d in dt],
  303. 'gtIds': [g['id'] for g in gt],
  304. 'dtMatches': dtm,
  305. 'gtMatches': gtm,
  306. 'dtScores': [d['score'] for d in dt],
  307. 'gtIgnore': gtIg,
  308. 'dtIgnore': dtIg,
  309. }
  310. def accumulate(self, p=None):
  311. '''
  312. Accumulate per image evaluation results and store the result in self.eval
  313. :param p: input params for evaluation
  314. :return: None
  315. '''
  316. print('Accumulating evaluation results...')
  317. tic = time.time()
  318. if not self.evalImgs:
  319. print('Please run evaluate() first')
  320. # allows input customized parameters
  321. if p is None:
  322. p = self.params
  323. p.catIds = p.catIds if p.useCats == 1 else [-1]
  324. T = len(p.iouThrs)
  325. R = len(p.recThrs)
  326. K = len(p.catIds) if p.useCats else 1
  327. A = len(p.areaRng)
  328. M = len(p.maxDets)
  329. # -1 for the precision of absent categories
  330. precision = -np.ones((T, R, K, A, M))
  331. recall = -np.ones((T, K, A, M))
  332. scores = -np.ones((T, R, K, A, M))
  333. # create dictionary for future indexing
  334. _pe = self._paramsEval
  335. catIds = _pe.catIds if _pe.useCats else [-1]
  336. setK = set(catIds)
  337. setA = set(map(tuple, _pe.areaRng))
  338. setM = set(_pe.maxDets)
  339. setI = set(_pe.imgIds)
  340. # get inds to evaluate
  341. k_list = [n for n, k in enumerate(p.catIds) if k in setK]
  342. m_list = [m for n, m in enumerate(p.maxDets) if m in setM]
  343. a_list = [n for n, a in enumerate(
  344. map(lambda x: tuple(x), p.areaRng)) if a in setA]
  345. i_list = [n for n, i in enumerate(p.imgIds) if i in setI]
  346. I0 = len(_pe.imgIds)
  347. A0 = len(_pe.areaRng)
  348. # retrieve E at each category, area range, and max number of detections
  349. for k, k0 in enumerate(k_list):
  350. Nk = k0*A0*I0
  351. for a, a0 in enumerate(a_list):
  352. Na = a0*I0
  353. for m, maxDet in enumerate(m_list):
  354. E = [self.evalImgs[Nk + Na + i] for i in i_list]
  355. E = [e for e in E if not e is None]
  356. if len(E) == 0:
  357. continue
  358. dtScores = np.concatenate(
  359. [e['dtScores'][0:maxDet] for e in E])
  360. # different sorting method generates slightly different results.
  361. # mergesort is used to be consistent as Matlab implementation.
  362. inds = np.argsort(-dtScores, kind='mergesort')
  363. dtScoresSorted = dtScores[inds]
  364. dtm = np.concatenate([e['dtMatches'][:, 0:maxDet]
  365. for e in E], axis=1)[:, inds]
  366. dtIg = np.concatenate(
  367. [e['dtIgnore'][:, 0:maxDet] for e in E], axis=1)[:, inds]
  368. gtIg = np.concatenate([e['gtIgnore'] for e in E])
  369. npig = np.count_nonzero(gtIg == 0)
  370. if npig == 0:
  371. continue
  372. tps = np.logical_and(dtm, np.logical_not(dtIg))
  373. fps = np.logical_and(
  374. np.logical_not(dtm), np.logical_not(dtIg))
  375. tp_sum = np.cumsum(tps, axis=1).astype(dtype=np.float)
  376. fp_sum = np.cumsum(fps, axis=1).astype(dtype=np.float)
  377. for t, (tp, fp) in enumerate(zip(tp_sum, fp_sum)):
  378. tp = np.array(tp)
  379. fp = np.array(fp)
  380. nd = len(tp)
  381. rc = tp / npig
  382. pr = tp / (fp+tp+np.spacing(1))
  383. q = np.zeros((R,))
  384. ss = np.zeros((R,))
  385. if nd:
  386. recall[t, k, a, m] = rc[-1]
  387. else:
  388. recall[t, k, a, m] = 0
  389. # numpy is slow without cython optimization for accessing elements
  390. # use python array gets significant speed improvement
  391. pr = pr.tolist()
  392. q = q.tolist()
  393. for i in range(nd-1, 0, -1):
  394. if pr[i] > pr[i-1]:
  395. pr[i-1] = pr[i]
  396. inds = np.searchsorted(rc, p.recThrs, side='left')
  397. try:
  398. for ri, pi in enumerate(inds):
  399. q[ri] = pr[pi]
  400. ss[ri] = dtScoresSorted[pi]
  401. except:
  402. pass
  403. precision[t, :, k, a, m] = np.array(q)
  404. scores[t, :, k, a, m] = np.array(ss)
  405. self.eval = {
  406. 'params': p,
  407. 'counts': [T, R, K, A, M],
  408. 'date': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  409. 'precision': precision,
  410. 'recall': recall,
  411. 'scores': scores,
  412. }
  413. toc = time.time()
  414. print('DONE (t={:0.2f}s).'.format(toc-tic))
  415. def summarize(self):
  416. '''
  417. Compute and display summary metrics for evaluation results.
  418. Note this functin can *only* be applied on the default parameter setting
  419. '''
  420. def _summarize(ap=1, iouThr=None, areaRng='all', maxDets=100):
  421. p = self.params
  422. iStr = ' {:<18} {} @[ IoU={:<9} | area={:>6s} | maxDets={:>3d} ] = {:0.3f}'
  423. titleStr = 'Average Precision' if ap == 1 else 'Average Recall'
  424. typeStr = '(AP)' if ap == 1 else '(AR)'
  425. iouStr = '{:0.2f}:{:0.2f}'.format(p.iouThrs[0], p.iouThrs[-1]) \
  426. if iouThr is None else '{:0.2f}'.format(iouThr)
  427. aind = [i for i, aRng in enumerate(
  428. p.areaRngLbl) if aRng == areaRng]
  429. mind = [i for i, mDet in enumerate(p.maxDets) if mDet == maxDets]
  430. if ap == 1:
  431. # dimension of precision: [TxRxKxAxM]
  432. s = self.eval['precision']
  433. # IoU
  434. if iouThr is not None:
  435. t = np.where(iouThr == p.iouThrs)[0]
  436. s = s[t]
  437. s = s[:, :, :, aind, mind]
  438. else:
  439. # dimension of recall: [TxKxAxM]
  440. s = self.eval['recall']
  441. if iouThr is not None:
  442. t = np.where(iouThr == p.iouThrs)[0]
  443. s = s[t]
  444. s = s[:, :, aind, mind]
  445. if len(s[s > -1]) == 0:
  446. mean_s = -1
  447. else:
  448. mean_s = np.mean(s[s > -1])
  449. print(iStr.format(titleStr, typeStr, iouStr, areaRng, maxDets, mean_s))
  450. return mean_s
  451. def _summarizeDets():
  452. stats = np.zeros((32,))
  453. stats[0] = _summarize(1)
  454. stats[1] = _summarize(1, iouThr=.5, maxDets=self.params.maxDets[2])
  455. stats[2] = _summarize(
  456. 1, iouThr=.75, maxDets=self.params.maxDets[2])
  457. stats[3] = _summarize(1, areaRng='small',
  458. maxDets=self.params.maxDets[2])
  459. stats[4] = _summarize(1, areaRng='medium',
  460. maxDets=self.params.maxDets[2])
  461. stats[5] = _summarize(1, areaRng='large',
  462. maxDets=self.params.maxDets[2])
  463. stats[6] = _summarize(0, maxDets=self.params.maxDets[0])
  464. stats[7] = _summarize(0, maxDets=self.params.maxDets[1])
  465. stats[8] = _summarize(0, maxDets=self.params.maxDets[2])
  466. stats[9] = _summarize(0, areaRng='small',
  467. maxDets=self.params.maxDets[2])
  468. stats[10] = _summarize(0, areaRng='medium',
  469. maxDets=self.params.maxDets[2])
  470. stats[11] = _summarize(
  471. 0, areaRng='large', maxDets=self.params.maxDets[2])
  472. stats[12] = _summarize(
  473. 1, iouThr=.5, maxDets=self.params.maxDets[2])
  474. stats[13] = _summarize(
  475. 1, iouThr=.55, maxDets=self.params.maxDets[2])
  476. stats[14] = _summarize(
  477. 1, iouThr=.60, maxDets=self.params.maxDets[2])
  478. stats[15] = _summarize(
  479. 1, iouThr=.65, maxDets=self.params.maxDets[2])
  480. stats[16] = _summarize(
  481. 1, iouThr=.70, maxDets=self.params.maxDets[2])
  482. stats[17] = _summarize(
  483. 1, iouThr=.75, maxDets=self.params.maxDets[2])
  484. stats[18] = _summarize(
  485. 1, iouThr=.80, maxDets=self.params.maxDets[2])
  486. stats[19] = _summarize(
  487. 1, iouThr=.85, maxDets=self.params.maxDets[2])
  488. stats[20] = _summarize(
  489. 1, iouThr=.90, maxDets=self.params.maxDets[2])
  490. stats[21] = _summarize(
  491. 1, iouThr=.95, maxDets=self.params.maxDets[2])
  492. stats[22] = _summarize(
  493. 0, iouThr=.5, maxDets=self.params.maxDets[2])
  494. stats[23] = _summarize(
  495. 0, iouThr=.55, maxDets=self.params.maxDets[2])
  496. stats[24] = _summarize(
  497. 0, iouThr=.60, maxDets=self.params.maxDets[2])
  498. stats[25] = _summarize(
  499. 0, iouThr=.65, maxDets=self.params.maxDets[2])
  500. stats[26] = _summarize(
  501. 0, iouThr=.70, maxDets=self.params.maxDets[2])
  502. stats[27] = _summarize(
  503. 0, iouThr=.75, maxDets=self.params.maxDets[2])
  504. stats[28] = _summarize(
  505. 0, iouThr=.80, maxDets=self.params.maxDets[2])
  506. stats[29] = _summarize(
  507. 0, iouThr=.85, maxDets=self.params.maxDets[2])
  508. stats[30] = _summarize(
  509. 0, iouThr=.90, maxDets=self.params.maxDets[2])
  510. stats[31] = _summarize(
  511. 0, iouThr=.95, maxDets=self.params.maxDets[2])
  512. return stats
  513. def _summarizeKps():
  514. stats = np.zeros((10,))
  515. stats[0] = _summarize(1, maxDets=20)
  516. stats[1] = _summarize(1, maxDets=20, iouThr=.5)
  517. stats[2] = _summarize(1, maxDets=20, iouThr=.75)
  518. stats[3] = _summarize(1, maxDets=20, areaRng='medium')
  519. stats[4] = _summarize(1, maxDets=20, areaRng='large')
  520. stats[5] = _summarize(0, maxDets=20)
  521. stats[6] = _summarize(0, maxDets=20, iouThr=.5)
  522. stats[7] = _summarize(0, maxDets=20, iouThr=.75)
  523. stats[8] = _summarize(0, maxDets=20, areaRng='medium')
  524. stats[9] = _summarize(0, maxDets=20, areaRng='large')
  525. return stats
  526. if not self.eval:
  527. raise Exception('Please run accumulate() first')
  528. iouType = self.params.iouType
  529. if iouType == 'segm' or iouType == 'bbox':
  530. summarize = _summarizeDets
  531. elif iouType == 'keypoints':
  532. summarize = _summarizeKps
  533. self.stats = summarize()
  534. def __str__(self):
  535. self.summarize()
  536. class Params:
  537. '''
  538. Params for coco evaluation api
  539. '''
  540. def setDetParams(self):
  541. self.imgIds = []
  542. self.catIds = []
  543. # np.arange causes trouble. the data point on arange is slightly larger than the true value
  544. self.iouThrs = np.linspace(.5, 0.95, int(
  545. np.round((0.95 - .5) / .05)) + 1, endpoint=True)
  546. self.recThrs = np.linspace(.0, 1.00, int(
  547. np.round((1.00 - .0) / .01)) + 1, endpoint=True)
  548. self.maxDets = [1, 10, 100]
  549. self.areaRng = [[0 ** 2, 1e5 ** 2], [0 ** 2, 32 ** 2],
  550. [32 ** 2, 96 ** 2], [96 ** 2, 1e5 ** 2]]
  551. self.areaRngLbl = ['all', 'small', 'medium', 'large']
  552. self.useCats = 1
  553. def setKpParams(self):
  554. self.imgIds = []
  555. self.catIds = []
  556. # np.arange causes trouble. the data point on arange is slightly larger than the true value
  557. self.iouThrs = np.linspace(.5, 0.95, int(
  558. np.round((0.95 - .5) / .05)) + 1, endpoint=True)
  559. self.recThrs = np.linspace(.0, 1.00, int(
  560. np.round((1.00 - .0) / .01)) + 1, endpoint=True)
  561. self.maxDets = [20]
  562. self.areaRng = [[0 ** 2, 1e5 ** 2],
  563. [32 ** 2, 96 ** 2], [96 ** 2, 1e5 ** 2]]
  564. self.areaRngLbl = ['all', 'medium', 'large']
  565. self.useCats = 1
  566. self.kpt_oks_sigmas = np.array(
  567. [.26, .25, .25, .35, .35, .79, .79, .72, .72, .62, .62, 1.07, 1.07, .87, .87, .89, .89])/10.0
  568. def __init__(self, iouType='segm'):
  569. if iouType == 'segm' or iouType == 'bbox':
  570. self.setDetParams()
  571. elif iouType == 'keypoints':
  572. self.setKpParams()
  573. else:
  574. raise Exception('iouType not supported')
  575. self.iouType = iouType
  576. # useSegm is deprecated
  577. self.useSegm = None