coco_panoptic.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. # Copyright (c) OpenMMLab. All rights reserved.
  2. import os.path as osp
  3. from typing import Callable, List, Optional, Sequence, Union
  4. from mmdet.registry import DATASETS
  5. from .api_wrappers import COCOPanoptic
  6. from .coco import CocoDataset
  7. @DATASETS.register_module()
  8. class CocoPanopticDataset(CocoDataset):
  9. """Coco dataset for Panoptic segmentation.
  10. The annotation format is shown as follows. The `ann` field is optional
  11. for testing.
  12. .. code-block:: none
  13. [
  14. {
  15. 'filename': f'{image_id:012}.png',
  16. 'image_id':9
  17. 'segments_info':
  18. [
  19. {
  20. 'id': 8345037, (segment_id in panoptic png,
  21. convert from rgb)
  22. 'category_id': 51,
  23. 'iscrowd': 0,
  24. 'bbox': (x1, y1, w, h),
  25. 'area': 24315
  26. },
  27. ...
  28. ]
  29. },
  30. ...
  31. ]
  32. Args:
  33. ann_file (str): Annotation file path. Defaults to ''.
  34. metainfo (dict, optional): Meta information for dataset, such as class
  35. information. Defaults to None.
  36. data_root (str, optional): The root directory for ``data_prefix`` and
  37. ``ann_file``. Defaults to None.
  38. data_prefix (dict, optional): Prefix for training data. Defaults to
  39. ``dict(img=None, ann=None, seg=None)``. The prefix ``seg`` which is
  40. for panoptic segmentation map must be not None.
  41. filter_cfg (dict, optional): Config for filter data. Defaults to None.
  42. indices (int or Sequence[int], optional): Support using first few
  43. data in annotation file to facilitate training/testing on a smaller
  44. dataset. Defaults to None which means using all ``data_infos``.
  45. serialize_data (bool, optional): Whether to hold memory using
  46. serialized objects, when enabled, data loader workers can use
  47. shared RAM from master process instead of making a copy. Defaults
  48. to True.
  49. pipeline (list, optional): Processing pipeline. Defaults to [].
  50. test_mode (bool, optional): ``test_mode=True`` means in test phase.
  51. Defaults to False.
  52. lazy_init (bool, optional): Whether to load annotation during
  53. instantiation. In some cases, such as visualization, only the meta
  54. information of the dataset is needed, which is not necessary to
  55. load annotation file. ``Basedataset`` can skip load annotations to
  56. save time by set ``lazy_init=False``. Defaults to False.
  57. max_refetch (int, optional): If ``Basedataset.prepare_data`` get a
  58. None img. The maximum extra number of cycles to get a valid
  59. image. Defaults to 1000.
  60. """
  61. METAINFO = {
  62. 'classes':
  63. ('person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train',
  64. 'truck', 'boat', 'traffic light', 'fire hydrant', 'stop sign',
  65. 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep',
  66. 'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella',
  67. 'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard',
  68. 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard',
  69. 'surfboard', 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork',
  70. 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange',
  71. 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair',
  72. 'couch', 'potted plant', 'bed', 'dining table', 'toilet', 'tv',
  73. 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave',
  74. 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase',
  75. 'scissors', 'teddy bear', 'hair drier', 'toothbrush', 'banner',
  76. 'blanket', 'bridge', 'cardboard', 'counter', 'curtain', 'door-stuff',
  77. 'floor-wood', 'flower', 'fruit', 'gravel', 'house', 'light',
  78. 'mirror-stuff', 'net', 'pillow', 'platform', 'playingfield',
  79. 'railroad', 'river', 'road', 'roof', 'sand', 'sea', 'shelf', 'snow',
  80. 'stairs', 'tent', 'towel', 'wall-brick', 'wall-stone', 'wall-tile',
  81. 'wall-wood', 'water-other', 'window-blind', 'window-other',
  82. 'tree-merged', 'fence-merged', 'ceiling-merged', 'sky-other-merged',
  83. 'cabinet-merged', 'table-merged', 'floor-other-merged',
  84. 'pavement-merged', 'mountain-merged', 'grass-merged', 'dirt-merged',
  85. 'paper-merged', 'food-other-merged', 'building-other-merged',
  86. 'rock-merged', 'wall-other-merged', 'rug-merged'),
  87. 'thing_classes':
  88. ('person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train',
  89. 'truck', 'boat', 'traffic light', 'fire hydrant', 'stop sign',
  90. 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep',
  91. 'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella',
  92. 'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard',
  93. 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard',
  94. 'surfboard', 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork',
  95. 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange',
  96. 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair',
  97. 'couch', 'potted plant', 'bed', 'dining table', 'toilet', 'tv',
  98. 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave',
  99. 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase',
  100. 'scissors', 'teddy bear', 'hair drier', 'toothbrush'),
  101. 'stuff_classes':
  102. ('banner', 'blanket', 'bridge', 'cardboard', 'counter', 'curtain',
  103. 'door-stuff', 'floor-wood', 'flower', 'fruit', 'gravel', 'house',
  104. 'light', 'mirror-stuff', 'net', 'pillow', 'platform', 'playingfield',
  105. 'railroad', 'river', 'road', 'roof', 'sand', 'sea', 'shelf', 'snow',
  106. 'stairs', 'tent', 'towel', 'wall-brick', 'wall-stone', 'wall-tile',
  107. 'wall-wood', 'water-other', 'window-blind', 'window-other',
  108. 'tree-merged', 'fence-merged', 'ceiling-merged', 'sky-other-merged',
  109. 'cabinet-merged', 'table-merged', 'floor-other-merged',
  110. 'pavement-merged', 'mountain-merged', 'grass-merged', 'dirt-merged',
  111. 'paper-merged', 'food-other-merged', 'building-other-merged',
  112. 'rock-merged', 'wall-other-merged', 'rug-merged'),
  113. 'palette':
  114. [(220, 20, 60), (119, 11, 32), (0, 0, 142), (0, 0, 230), (106, 0, 228),
  115. (0, 60, 100), (0, 80, 100), (0, 0, 70), (0, 0, 192), (250, 170, 30),
  116. (100, 170, 30), (220, 220, 0), (175, 116, 175), (250, 0, 30),
  117. (165, 42, 42), (255, 77, 255), (0, 226, 252), (182, 182, 255),
  118. (0, 82, 0), (120, 166, 157), (110, 76, 0), (174, 57, 255),
  119. (199, 100, 0), (72, 0, 118), (255, 179, 240), (0, 125, 92),
  120. (209, 0, 151), (188, 208, 182), (0, 220, 176), (255, 99, 164),
  121. (92, 0, 73), (133, 129, 255), (78, 180, 255), (0, 228, 0),
  122. (174, 255, 243), (45, 89, 255), (134, 134, 103), (145, 148, 174),
  123. (255, 208, 186), (197, 226, 255), (171, 134, 1), (109, 63, 54),
  124. (207, 138, 255), (151, 0, 95), (9, 80, 61), (84, 105, 51),
  125. (74, 65, 105), (166, 196, 102), (208, 195, 210), (255, 109, 65),
  126. (0, 143, 149), (179, 0, 194), (209, 99, 106), (5, 121, 0),
  127. (227, 255, 205), (147, 186, 208), (153, 69, 1), (3, 95, 161),
  128. (163, 255, 0), (119, 0, 170), (0, 182, 199), (0, 165, 120),
  129. (183, 130, 88), (95, 32, 0), (130, 114, 135), (110, 129, 133),
  130. (166, 74, 118), (219, 142, 185), (79, 210, 114), (178, 90, 62),
  131. (65, 70, 15), (127, 167, 115), (59, 105, 106), (142, 108, 45),
  132. (196, 172, 0), (95, 54, 80), (128, 76, 255), (201, 57, 1),
  133. (246, 0, 122), (191, 162, 208), (255, 255, 128), (147, 211, 203),
  134. (150, 100, 100), (168, 171, 172), (146, 112, 198), (210, 170, 100),
  135. (92, 136, 89), (218, 88, 184), (241, 129, 0), (217, 17, 255),
  136. (124, 74, 181), (70, 70, 70), (255, 228, 255), (154, 208, 0),
  137. (193, 0, 92), (76, 91, 113), (255, 180, 195), (106, 154, 176),
  138. (230, 150, 140), (60, 143, 255), (128, 64, 128), (92, 82, 55),
  139. (254, 212, 124), (73, 77, 174), (255, 160, 98), (255, 255, 255),
  140. (104, 84, 109), (169, 164, 131), (225, 199, 255), (137, 54, 74),
  141. (135, 158, 223), (7, 246, 231), (107, 255, 200), (58, 41, 149),
  142. (183, 121, 142), (255, 73, 97), (107, 142, 35), (190, 153, 153),
  143. (146, 139, 141), (70, 130, 180), (134, 199, 156), (209, 226, 140),
  144. (96, 36, 108), (96, 96, 96), (64, 170, 64), (152, 251, 152),
  145. (208, 229, 228), (206, 186, 171), (152, 161, 64), (116, 112, 0),
  146. (0, 114, 143), (102, 102, 156), (250, 141, 255)]
  147. }
  148. COCOAPI = COCOPanoptic
  149. # ann_id is not unique in coco panoptic dataset.
  150. ANN_ID_UNIQUE = False
  151. def __init__(self,
  152. ann_file: str = '',
  153. metainfo: Optional[dict] = None,
  154. data_root: Optional[str] = None,
  155. data_prefix: dict = dict(img=None, ann=None, seg=None),
  156. filter_cfg: Optional[dict] = None,
  157. indices: Optional[Union[int, Sequence[int]]] = None,
  158. serialize_data: bool = True,
  159. pipeline: List[Union[dict, Callable]] = [],
  160. test_mode: bool = False,
  161. lazy_init: bool = False,
  162. max_refetch: int = 1000,
  163. backend_args: dict = None,
  164. **kwargs) -> None:
  165. super().__init__(
  166. ann_file=ann_file,
  167. metainfo=metainfo,
  168. data_root=data_root,
  169. data_prefix=data_prefix,
  170. filter_cfg=filter_cfg,
  171. indices=indices,
  172. serialize_data=serialize_data,
  173. pipeline=pipeline,
  174. test_mode=test_mode,
  175. lazy_init=lazy_init,
  176. max_refetch=max_refetch,
  177. backend_args=backend_args,
  178. **kwargs)
  179. def parse_data_info(self, raw_data_info: dict) -> dict:
  180. """Parse raw annotation to target format.
  181. Args:
  182. raw_data_info (dict): Raw data information load from ``ann_file``.
  183. Returns:
  184. dict: Parsed annotation.
  185. """
  186. img_info = raw_data_info['raw_img_info']
  187. ann_info = raw_data_info['raw_ann_info']
  188. # filter out unmatched annotations which have
  189. # same segment_id but belong to other image
  190. ann_info = [
  191. ann for ann in ann_info if ann['image_id'] == img_info['img_id']
  192. ]
  193. data_info = {}
  194. img_path = osp.join(self.data_prefix['img'], img_info['file_name'])
  195. if self.data_prefix.get('seg', None):
  196. seg_map_path = osp.join(
  197. self.data_prefix['seg'],
  198. img_info['file_name'].replace('jpg', 'png'))
  199. else:
  200. seg_map_path = None
  201. data_info['img_path'] = img_path
  202. data_info['img_id'] = img_info['img_id']
  203. data_info['seg_map_path'] = seg_map_path
  204. data_info['height'] = img_info['height']
  205. data_info['width'] = img_info['width']
  206. instances = []
  207. segments_info = []
  208. for ann in ann_info:
  209. instance = {}
  210. x1, y1, w, h = ann['bbox']
  211. if ann['area'] <= 0 or w < 1 or h < 1:
  212. continue
  213. bbox = [x1, y1, x1 + w, y1 + h]
  214. category_id = ann['category_id']
  215. contiguous_cat_id = self.cat2label[category_id]
  216. is_thing = self.coco.load_cats(ids=category_id)[0]['isthing']
  217. if is_thing:
  218. is_crowd = ann.get('iscrowd', False)
  219. instance['bbox'] = bbox
  220. instance['bbox_label'] = contiguous_cat_id
  221. if not is_crowd:
  222. instance['ignore_flag'] = 0
  223. else:
  224. instance['ignore_flag'] = 1
  225. is_thing = False
  226. segment_info = {
  227. 'id': ann['id'],
  228. 'category': contiguous_cat_id,
  229. 'is_thing': is_thing
  230. }
  231. segments_info.append(segment_info)
  232. if len(instance) > 0 and is_thing:
  233. instances.append(instance)
  234. data_info['instances'] = instances
  235. data_info['segments_info'] = segments_info
  236. return data_info
  237. def filter_data(self) -> List[dict]:
  238. """Filter images too small or without ground truth.
  239. Returns:
  240. List[dict]: ``self.data_list`` after filtering.
  241. """
  242. if self.test_mode:
  243. return self.data_list
  244. if self.filter_cfg is None:
  245. return self.data_list
  246. filter_empty_gt = self.filter_cfg.get('filter_empty_gt', False)
  247. min_size = self.filter_cfg.get('min_size', 0)
  248. ids_with_ann = set()
  249. # check whether images have legal thing annotations.
  250. for data_info in self.data_list:
  251. for segment_info in data_info['segments_info']:
  252. if not segment_info['is_thing']:
  253. continue
  254. ids_with_ann.add(data_info['img_id'])
  255. valid_data_list = []
  256. for data_info in self.data_list:
  257. img_id = data_info['img_id']
  258. width = data_info['width']
  259. height = data_info['height']
  260. if filter_empty_gt and img_id not in ids_with_ann:
  261. continue
  262. if min(width, height) >= min_size:
  263. valid_data_list.append(data_info)
  264. return valid_data_list