coco_eval.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. # Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from __future__ import absolute_import
  15. from __future__ import division
  16. from __future__ import print_function
  17. from __future__ import unicode_literals
  18. import os
  19. import sys
  20. import json
  21. import cv2
  22. import numpy as np
  23. import logging
  24. logger = logging.getLogger(__name__)
  25. __all__ = [
  26. 'bbox_eval',
  27. 'mask_eval',
  28. 'bbox2out',
  29. 'mask2out',
  30. 'get_category_info',
  31. 'proposal_eval',
  32. 'cocoapi_eval',
  33. ]
  34. def clip_bbox(bbox, im_size=None):
  35. h = 1. if im_size is None else im_size[0]
  36. w = 1. if im_size is None else im_size[1]
  37. xmin = max(min(bbox[0], w), 0.)
  38. ymin = max(min(bbox[1], h), 0.)
  39. xmax = max(min(bbox[2], w), 0.)
  40. ymax = max(min(bbox[3], h), 0.)
  41. return xmin, ymin, xmax, ymax
  42. def proposal_eval(results, anno_file, outfile, max_dets=(100, 300, 1000)):
  43. assert 'proposal' in results[0]
  44. assert outfile.endswith('.json')
  45. xywh_results = proposal2out(results)
  46. assert len(
  47. xywh_results) > 0, "The number of valid proposal detected is zero.\n \
  48. Please use reasonable model and check input data."
  49. with open(outfile, 'w') as f:
  50. json.dump(xywh_results, f)
  51. cocoapi_eval(outfile, 'proposal', anno_file=anno_file, max_dets=max_dets)
  52. # flush coco evaluation result
  53. sys.stdout.flush()
  54. def bbox_eval(results,
  55. anno_file,
  56. outfile,
  57. with_background=True,
  58. is_bbox_normalized=False,
  59. save_only=False):
  60. assert 'bbox' in results[0]
  61. assert outfile.endswith('.json')
  62. from pycocotools.coco import COCO
  63. coco_gt = COCO(anno_file)
  64. cat_ids = coco_gt.getCatIds()
  65. # when with_background = True, mapping category to classid, like:
  66. # background:0, first_class:1, second_class:2, ...
  67. clsid2catid = dict(
  68. {i + int(with_background): catid
  69. for i, catid in enumerate(cat_ids)})
  70. xywh_results = bbox2out(
  71. results, clsid2catid, is_bbox_normalized=is_bbox_normalized)
  72. if len(xywh_results) == 0:
  73. logger.warning("The number of valid bbox detected is zero.\n \
  74. Please use reasonable model and check input data.\n \
  75. stop eval!")
  76. return [0.0]
  77. with open(outfile, 'w') as f:
  78. json.dump(xywh_results, f)
  79. if save_only:
  80. logger.info('The bbox result is saved to {} and do not '
  81. 'evaluate the mAP.'.format(outfile))
  82. return
  83. map_stats = cocoapi_eval(outfile, 'bbox', coco_gt=coco_gt)
  84. # flush coco evaluation result
  85. sys.stdout.flush()
  86. return map_stats
  87. def mask_eval(results,
  88. anno_file,
  89. outfile,
  90. resolution,
  91. thresh_binarize=0.5,
  92. save_only=False):
  93. """
  94. Format the output of mask and get mask ap by coco api evaluation.
  95. It will be used in Mask-RCNN.
  96. """
  97. assert 'mask' in results[0]
  98. assert outfile.endswith('.json')
  99. from pycocotools.coco import COCO
  100. coco_gt = COCO(anno_file)
  101. clsid2catid = {i + 1: v for i, v in enumerate(coco_gt.getCatIds())}
  102. segm_results = []
  103. for t in results:
  104. im_ids = np.array(t['im_id'][0])
  105. bboxes = t['bbox'][0]
  106. lengths = t['bbox'][1][0]
  107. masks = t['mask']
  108. if bboxes.shape == (1, 1) or bboxes is None:
  109. continue
  110. if len(bboxes.tolist()) == 0:
  111. continue
  112. s = 0
  113. for i in range(len(lengths)):
  114. num = lengths[i]
  115. im_id = int(im_ids[i][0])
  116. clsid_scores = bboxes[s:s + num][:, 0:2]
  117. mask = masks[s:s + num]
  118. s += num
  119. for j in range(num):
  120. clsid, score = clsid_scores[j].tolist()
  121. catid = int(clsid2catid[clsid])
  122. segm = mask[j]
  123. segm['counts'] = segm['counts'].decode('utf8')
  124. coco_res = {
  125. 'image_id': im_id,
  126. 'category_id': int(catid),
  127. 'segmentation': segm,
  128. 'score': score
  129. }
  130. segm_results.append(coco_res)
  131. if len(segm_results) == 0:
  132. logger.warning("The number of valid mask detected is zero.\n \
  133. Please use reasonable model and check input data.")
  134. return
  135. with open(outfile, 'w') as f:
  136. json.dump(segm_results, f)
  137. if save_only:
  138. logger.info('The mask result is saved to {} and do not '
  139. 'evaluate the mAP.'.format(outfile))
  140. return
  141. cocoapi_eval(outfile, 'segm', coco_gt=coco_gt)
  142. def segm_eval(results, anno_file, outfile, save_only=False):
  143. """
  144. Format the output of segmentation, category_id and score in mask.josn, and
  145. get mask ap by coco api evaluation. It will be used in instance segmentation
  146. networks, such as: SOLOv2.
  147. """
  148. assert 'segm' in results[0]
  149. assert outfile.endswith('.json')
  150. from pycocotools.coco import COCO
  151. coco_gt = COCO(anno_file)
  152. clsid2catid = {i: v for i, v in enumerate(coco_gt.getCatIds())}
  153. segm_results = []
  154. for t in results:
  155. im_id = int(t['im_id'][0][0])
  156. segs = t['segm']
  157. for mask in segs:
  158. catid = int(clsid2catid[mask[0]])
  159. masks = mask[1]
  160. mask_score = masks[1]
  161. segm = masks[0]
  162. segm['counts'] = segm['counts'].decode('utf8')
  163. coco_res = {
  164. 'image_id': im_id,
  165. 'category_id': catid,
  166. 'segmentation': segm,
  167. 'score': mask_score
  168. }
  169. segm_results.append(coco_res)
  170. if len(segm_results) == 0:
  171. logger.warning("The number of valid mask detected is zero.\n \
  172. Please use reasonable model and check input data.")
  173. return
  174. with open(outfile, 'w') as f:
  175. json.dump(segm_results, f)
  176. if save_only:
  177. logger.info('The mask result is saved to {} and do not '
  178. 'evaluate the mAP.'.format(outfile))
  179. return
  180. map_stats = cocoapi_eval(outfile, 'segm', coco_gt=coco_gt)
  181. return map_stats
  182. def cocoapi_eval(jsonfile,
  183. style,
  184. coco_gt=None,
  185. anno_file=None,
  186. max_dets=(100, 300, 1000)):
  187. """
  188. Args:
  189. jsonfile: Evaluation json file, eg: bbox.json, mask.json.
  190. style: COCOeval style, can be `bbox` , `segm` and `proposal`.
  191. coco_gt: Whether to load COCOAPI through anno_file,
  192. eg: coco_gt = COCO(anno_file)
  193. anno_file: COCO annotations file.
  194. max_dets: COCO evaluation maxDets.
  195. """
  196. assert coco_gt != None or anno_file != None
  197. from pycocotools.coco import COCO
  198. from pycocotools.cocoeval import COCOeval
  199. if coco_gt == None:
  200. coco_gt = COCO(anno_file)
  201. logger.info("Start evaluate...")
  202. coco_dt = coco_gt.loadRes(jsonfile)
  203. if style == 'proposal':
  204. coco_eval = COCOeval(coco_gt, coco_dt, 'bbox')
  205. coco_eval.params.useCats = 0
  206. coco_eval.params.maxDets = list(max_dets)
  207. else:
  208. coco_eval = COCOeval(coco_gt, coco_dt, style)
  209. coco_eval.evaluate()
  210. coco_eval.accumulate()
  211. coco_eval.summarize()
  212. return coco_eval.stats
  213. def proposal2out(results, is_bbox_normalized=False):
  214. xywh_res = []
  215. for t in results:
  216. bboxes = t['proposal'][0]
  217. lengths = t['proposal'][1][0]
  218. im_ids = np.array(t['im_id'][0]).flatten()
  219. assert len(lengths) == im_ids.size
  220. if bboxes.shape == (1, 1) or bboxes is None:
  221. continue
  222. k = 0
  223. for i in range(len(lengths)):
  224. num = lengths[i]
  225. im_id = int(im_ids[i])
  226. for j in range(num):
  227. dt = bboxes[k]
  228. xmin, ymin, xmax, ymax = dt.tolist()
  229. if is_bbox_normalized:
  230. xmin, ymin, xmax, ymax = \
  231. clip_bbox([xmin, ymin, xmax, ymax])
  232. w = xmax - xmin
  233. h = ymax - ymin
  234. else:
  235. w = xmax - xmin + 1
  236. h = ymax - ymin + 1
  237. bbox = [xmin, ymin, w, h]
  238. coco_res = {
  239. 'image_id': im_id,
  240. 'category_id': 1,
  241. 'bbox': bbox,
  242. 'score': 1.0
  243. }
  244. xywh_res.append(coco_res)
  245. k += 1
  246. return xywh_res
  247. def bbox2out(results, clsid2catid, is_bbox_normalized=False):
  248. """
  249. Args:
  250. results: request a dict, should include: `bbox`, `im_id`,
  251. if is_bbox_normalized=True, also need `im_shape`.
  252. clsid2catid: class id to category id map of COCO2017 dataset.
  253. is_bbox_normalized: whether or not bbox is normalized.
  254. """
  255. xywh_res = []
  256. for t in results:
  257. bboxes = t['bbox'][0]
  258. if len(t['bbox'][1]) == 0: continue
  259. lengths = t['bbox'][1][0]
  260. im_ids = np.array(t['im_id'][0]).flatten()
  261. if bboxes.shape == (1, 1) or bboxes is None or len(bboxes) == 0:
  262. continue
  263. k = 0
  264. for i in range(len(lengths)):
  265. num = lengths[i]
  266. im_id = int(im_ids[i])
  267. for j in range(num):
  268. dt = bboxes[k]
  269. clsid, score, xmin, ymin, xmax, ymax = dt.tolist()
  270. if clsid < 0: continue
  271. catid = (clsid2catid[int(clsid)])
  272. if is_bbox_normalized:
  273. xmin, ymin, xmax, ymax = \
  274. clip_bbox([xmin, ymin, xmax, ymax])
  275. w = xmax - xmin
  276. h = ymax - ymin
  277. im_shape = t['im_shape'][0][i].tolist()
  278. im_height, im_width = int(im_shape[0]), int(im_shape[1])
  279. xmin *= im_width
  280. ymin *= im_height
  281. w *= im_width
  282. h *= im_height
  283. else:
  284. # for yolov4
  285. # w = xmax - xmin
  286. # h = ymax - ymin
  287. w = xmax - xmin + 1
  288. h = ymax - ymin + 1
  289. bbox = [xmin, ymin, w, h]
  290. coco_res = {
  291. 'image_id': im_id,
  292. 'category_id': catid,
  293. 'bbox': bbox,
  294. 'score': score
  295. }
  296. xywh_res.append(coco_res)
  297. k += 1
  298. return xywh_res
  299. def mask2out(results, clsid2catid, resolution, thresh_binarize=0.5):
  300. import pycocotools.mask as mask_util
  301. scale = (resolution + 2.0) / resolution
  302. segm_res = []
  303. # for each batch
  304. for t in results:
  305. bboxes = t['bbox'][0]
  306. lengths = t['bbox'][1][0]
  307. im_ids = np.array(t['im_id'][0])
  308. if bboxes.shape == (1, 1) or bboxes is None:
  309. continue
  310. if len(bboxes.tolist()) == 0:
  311. continue
  312. masks = t['mask'][0]
  313. s = 0
  314. # for each sample
  315. for i in range(len(lengths)):
  316. num = lengths[i]
  317. im_id = int(im_ids[i][0])
  318. im_shape = t['im_shape'][0][i]
  319. bbox = bboxes[s:s + num][:, 2:]
  320. clsid_scores = bboxes[s:s + num][:, 0:2]
  321. mask = masks[s:s + num]
  322. s += num
  323. im_h = int(im_shape[0])
  324. im_w = int(im_shape[1])
  325. expand_bbox = expand_boxes(bbox, scale)
  326. expand_bbox = expand_bbox.astype(np.int32)
  327. padded_mask = np.zeros(
  328. (resolution + 2, resolution + 2), dtype=np.float32)
  329. for j in range(num):
  330. xmin, ymin, xmax, ymax = expand_bbox[j].tolist()
  331. clsid, score = clsid_scores[j].tolist()
  332. clsid = int(clsid)
  333. padded_mask[1:-1, 1:-1] = mask[j, clsid, :, :]
  334. catid = clsid2catid[clsid]
  335. w = xmax - xmin + 1
  336. h = ymax - ymin + 1
  337. w = np.maximum(w, 1)
  338. h = np.maximum(h, 1)
  339. resized_mask = cv2.resize(padded_mask, (w, h))
  340. resized_mask = np.array(
  341. resized_mask > thresh_binarize, dtype=np.uint8)
  342. im_mask = np.zeros((im_h, im_w), dtype=np.uint8)
  343. x0 = min(max(xmin, 0), im_w)
  344. x1 = min(max(xmax + 1, 0), im_w)
  345. y0 = min(max(ymin, 0), im_h)
  346. y1 = min(max(ymax + 1, 0), im_h)
  347. im_mask[y0:y1, x0:x1] = resized_mask[(y0 - ymin):(y1 - ymin), (
  348. x0 - xmin):(x1 - xmin)]
  349. segm = mask_util.encode(
  350. np.array(
  351. im_mask[:, :, np.newaxis], order='F'))[0]
  352. catid = clsid2catid[clsid]
  353. segm['counts'] = segm['counts'].decode('utf8')
  354. coco_res = {
  355. 'image_id': im_id,
  356. 'category_id': catid,
  357. 'segmentation': segm,
  358. 'score': score
  359. }
  360. segm_res.append(coco_res)
  361. return segm_res
  362. def segm2out(results, clsid2catid, thresh_binarize=0.5):
  363. import pycocotools.mask as mask_util
  364. segm_res = []
  365. # for each batch
  366. for t in results:
  367. segms = t['segm'][0].astype(np.uint8)
  368. clsid_labels = t['cate_label'][0]
  369. clsid_scores = t['cate_score'][0]
  370. lengths = segms.shape[0]
  371. im_id = int(t['im_id'][0][0])
  372. im_shape = t['im_shape'][0][0]
  373. if lengths == 0 or segms is None:
  374. continue
  375. # for each sample
  376. for i in range(lengths - 1):
  377. im_h = int(im_shape[0])
  378. im_w = int(im_shape[1])
  379. clsid = int(clsid_labels[i]) + 1
  380. catid = clsid2catid[clsid]
  381. score = clsid_scores[i]
  382. mask = segms[i]
  383. segm = mask_util.encode(
  384. np.array(
  385. mask[:, :, np.newaxis], order='F'))[0]
  386. segm['counts'] = segm['counts'].decode('utf8')
  387. coco_res = {
  388. 'image_id': im_id,
  389. 'category_id': catid,
  390. 'segmentation': segm,
  391. 'score': score
  392. }
  393. segm_res.append(coco_res)
  394. return segm_res
  395. def expand_boxes(boxes, scale):
  396. """
  397. Expand an array of boxes by a given scale.
  398. """
  399. w_half = (boxes[:, 2] - boxes[:, 0]) * .5
  400. h_half = (boxes[:, 3] - boxes[:, 1]) * .5
  401. x_c = (boxes[:, 2] + boxes[:, 0]) * .5
  402. y_c = (boxes[:, 3] + boxes[:, 1]) * .5
  403. w_half *= scale
  404. h_half *= scale
  405. boxes_exp = np.zeros(boxes.shape)
  406. boxes_exp[:, 0] = x_c - w_half
  407. boxes_exp[:, 2] = x_c + w_half
  408. boxes_exp[:, 1] = y_c - h_half
  409. boxes_exp[:, 3] = y_c + h_half
  410. return boxes_exp
  411. def get_category_info(anno_file=None,
  412. with_background=True,
  413. use_default_label=False):
  414. if use_default_label or anno_file is None \
  415. or not os.path.exists(anno_file):
  416. logger.info("Not found annotation file {}, load "
  417. "coco17 categories.".format(anno_file))
  418. return coco17_category_info(with_background)
  419. else:
  420. logger.info("Load categories from {}".format(anno_file))
  421. if anno_file.endswith('.json'):
  422. return get_category_info_from_anno(anno_file, with_background)
  423. else:
  424. return get_category_info_from_txt(anno_file, with_background)
  425. def get_category_info_from_txt(anno_file, with_background=True):
  426. """
  427. Get class id to category id map and category id
  428. to category name map from txt file.
  429. args:
  430. anno_file (str): label txt file path.
  431. with_background (bool, default True):
  432. whether load background as class 0.
  433. """
  434. with open(anno_file, "r") as f:
  435. catid_list = f.readlines()
  436. clsid2catid = {}
  437. catid2name = {}
  438. for i, catid in enumerate(catid_list):
  439. catid = catid.strip('\n\t\r')
  440. clsid2catid[i + int(with_background)] = i + 1
  441. catid2name[i + int(with_background)] = catid
  442. if with_background:
  443. clsid2catid.update({0: 0})
  444. catid2name.update({0: 'background'})
  445. return clsid2catid, catid2name
  446. def get_category_info_from_anno(anno_file, with_background=True):
  447. """
  448. Get class id to category id map and category id
  449. to category name map from annotation file.
  450. Args:
  451. anno_file (str): annotation file path
  452. with_background (bool, default True):
  453. whether load background as class 0.
  454. """
  455. from pycocotools.coco import COCO
  456. coco = COCO(anno_file)
  457. cats = coco.loadCats(coco.getCatIds())
  458. clsid2catid = {
  459. i + int(with_background): cat['id']
  460. for i, cat in enumerate(cats)
  461. }
  462. catid2name = {cat['id']: cat['name'] for cat in cats}
  463. if with_background:
  464. clsid2catid.update({0: 0})
  465. catid2name.update({0: 'background'})
  466. return clsid2catid, catid2name
  467. def coco17_category_info(with_background=True):
  468. """
  469. Get class id to category id map and category id
  470. to category name map of COCO2017 dataset
  471. Args:
  472. with_background (bool, default True):
  473. whether load background as class 0.
  474. """
  475. clsid2catid = {
  476. 1: 1,
  477. 2: 2,
  478. 3: 3,
  479. 4: 4,
  480. 5: 5,
  481. 6: 6,
  482. 7: 7,
  483. 8: 8,
  484. 9: 9,
  485. 10: 10,
  486. 11: 11,
  487. 12: 13,
  488. 13: 14,
  489. 14: 15,
  490. 15: 16,
  491. 16: 17,
  492. 17: 18,
  493. 18: 19,
  494. 19: 20,
  495. 20: 21,
  496. 21: 22,
  497. 22: 23,
  498. 23: 24,
  499. 24: 25,
  500. 25: 27,
  501. 26: 28,
  502. 27: 31,
  503. 28: 32,
  504. 29: 33,
  505. 30: 34,
  506. 31: 35,
  507. 32: 36,
  508. 33: 37,
  509. 34: 38,
  510. 35: 39,
  511. 36: 40,
  512. 37: 41,
  513. 38: 42,
  514. 39: 43,
  515. 40: 44,
  516. 41: 46,
  517. 42: 47,
  518. 43: 48,
  519. 44: 49,
  520. 45: 50,
  521. 46: 51,
  522. 47: 52,
  523. 48: 53,
  524. 49: 54,
  525. 50: 55,
  526. 51: 56,
  527. 52: 57,
  528. 53: 58,
  529. 54: 59,
  530. 55: 60,
  531. 56: 61,
  532. 57: 62,
  533. 58: 63,
  534. 59: 64,
  535. 60: 65,
  536. 61: 67,
  537. 62: 70,
  538. 63: 72,
  539. 64: 73,
  540. 65: 74,
  541. 66: 75,
  542. 67: 76,
  543. 68: 77,
  544. 69: 78,
  545. 70: 79,
  546. 71: 80,
  547. 72: 81,
  548. 73: 82,
  549. 74: 84,
  550. 75: 85,
  551. 76: 86,
  552. 77: 87,
  553. 78: 88,
  554. 79: 89,
  555. 80: 90
  556. }
  557. catid2name = {
  558. 0: 'background',
  559. 1: 'person',
  560. 2: 'bicycle',
  561. 3: 'car',
  562. 4: 'motorcycle',
  563. 5: 'airplane',
  564. 6: 'bus',
  565. 7: 'train',
  566. 8: 'truck',
  567. 9: 'boat',
  568. 10: 'traffic light',
  569. 11: 'fire hydrant',
  570. 13: 'stop sign',
  571. 14: 'parking meter',
  572. 15: 'bench',
  573. 16: 'bird',
  574. 17: 'cat',
  575. 18: 'dog',
  576. 19: 'horse',
  577. 20: 'sheep',
  578. 21: 'cow',
  579. 22: 'elephant',
  580. 23: 'bear',
  581. 24: 'zebra',
  582. 25: 'giraffe',
  583. 27: 'backpack',
  584. 28: 'umbrella',
  585. 31: 'handbag',
  586. 32: 'tie',
  587. 33: 'suitcase',
  588. 34: 'frisbee',
  589. 35: 'skis',
  590. 36: 'snowboard',
  591. 37: 'sports ball',
  592. 38: 'kite',
  593. 39: 'baseball bat',
  594. 40: 'baseball glove',
  595. 41: 'skateboard',
  596. 42: 'surfboard',
  597. 43: 'tennis racket',
  598. 44: 'bottle',
  599. 46: 'wine glass',
  600. 47: 'cup',
  601. 48: 'fork',
  602. 49: 'knife',
  603. 50: 'spoon',
  604. 51: 'bowl',
  605. 52: 'banana',
  606. 53: 'apple',
  607. 54: 'sandwich',
  608. 55: 'orange',
  609. 56: 'broccoli',
  610. 57: 'carrot',
  611. 58: 'hot dog',
  612. 59: 'pizza',
  613. 60: 'donut',
  614. 61: 'cake',
  615. 62: 'chair',
  616. 63: 'couch',
  617. 64: 'potted plant',
  618. 65: 'bed',
  619. 67: 'dining table',
  620. 70: 'toilet',
  621. 72: 'tv',
  622. 73: 'laptop',
  623. 74: 'mouse',
  624. 75: 'remote',
  625. 76: 'keyboard',
  626. 77: 'cell phone',
  627. 78: 'microwave',
  628. 79: 'oven',
  629. 80: 'toaster',
  630. 81: 'sink',
  631. 82: 'refrigerator',
  632. 84: 'book',
  633. 85: 'clock',
  634. 86: 'vase',
  635. 87: 'scissors',
  636. 88: 'teddy bear',
  637. 89: 'hair drier',
  638. 90: 'toothbrush'
  639. }
  640. if not with_background:
  641. clsid2catid = {k - 1: v for k, v in clsid2catid.items()}
  642. catid2name.pop(0)
  643. else:
  644. clsid2catid.update({0: 0})
  645. return clsid2catid, catid2name