base_det_dataset.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. # Copyright (c) OpenMMLab. All rights reserved.
  2. import os.path as osp
  3. from typing import List, Optional
  4. from mmengine.dataset import BaseDataset
  5. from mmengine.fileio import load
  6. from mmengine.utils import is_abs
  7. from ..registry import DATASETS
  8. @DATASETS.register_module()
  9. class BaseDetDataset(BaseDataset):
  10. """Base dataset for detection.
  11. Args:
  12. proposal_file (str, optional): Proposals file path. Defaults to None.
  13. file_client_args (dict): Arguments to instantiate the
  14. corresponding backend in mmdet <= 3.0.0rc6. Defaults to None.
  15. backend_args (dict, optional): Arguments to instantiate the
  16. corresponding backend. Defaults to None.
  17. return_classes (bool): Whether to return class information
  18. for open vocabulary-based algorithms. Defaults to False.
  19. """
  20. def __init__(self,
  21. *args,
  22. seg_map_suffix: str = '.png',
  23. proposal_file: Optional[str] = None,
  24. file_client_args: dict = None,
  25. backend_args: dict = None,
  26. return_classes: bool = False,
  27. **kwargs) -> None:
  28. self.seg_map_suffix = seg_map_suffix
  29. self.proposal_file = proposal_file
  30. self.backend_args = backend_args
  31. self.return_classes = return_classes
  32. if file_client_args is not None:
  33. raise RuntimeError(
  34. 'The `file_client_args` is deprecated, '
  35. 'please use `backend_args` instead, please refer to'
  36. 'https://github.com/open-mmlab/mmdetection/blob/main/configs/_base_/datasets/coco_detection.py' # noqa: E501
  37. )
  38. super().__init__(*args, **kwargs)
  39. def full_init(self) -> None:
  40. """Load annotation file and set ``BaseDataset._fully_initialized`` to
  41. True.
  42. If ``lazy_init=False``, ``full_init`` will be called during the
  43. instantiation and ``self._fully_initialized`` will be set to True. If
  44. ``obj._fully_initialized=False``, the class method decorated by
  45. ``force_full_init`` will call ``full_init`` automatically.
  46. Several steps to initialize annotation:
  47. - load_data_list: Load annotations from annotation file.
  48. - load_proposals: Load proposals from proposal file, if
  49. `self.proposal_file` is not None.
  50. - filter data information: Filter annotations according to
  51. filter_cfg.
  52. - slice_data: Slice dataset according to ``self._indices``
  53. - serialize_data: Serialize ``self.data_list`` if
  54. ``self.serialize_data`` is True.
  55. """
  56. if self._fully_initialized:
  57. return
  58. # load data information
  59. self.data_list = self.load_data_list()
  60. # get proposals from file
  61. if self.proposal_file is not None:
  62. self.load_proposals()
  63. # filter illegal data, such as data that has no annotations.
  64. self.data_list = self.filter_data()
  65. # Get subset data according to indices.
  66. if self._indices is not None:
  67. self.data_list = self._get_unserialized_subset(self._indices)
  68. # serialize data_list
  69. if self.serialize_data:
  70. self.data_bytes, self.data_address = self._serialize_data()
  71. self._fully_initialized = True
  72. def load_proposals(self) -> None:
  73. """Load proposals from proposals file.
  74. The `proposals_list` should be a dict[img_path: proposals]
  75. with the same length as `data_list`. And the `proposals` should be
  76. a `dict` or :obj:`InstanceData` usually contains following keys.
  77. - bboxes (np.ndarry): Has a shape (num_instances, 4),
  78. the last dimension 4 arrange as (x1, y1, x2, y2).
  79. - scores (np.ndarry): Classification scores, has a shape
  80. (num_instance, ).
  81. """
  82. # TODO: Add Unit Test after fully support Dump-Proposal Metric
  83. if not is_abs(self.proposal_file):
  84. self.proposal_file = osp.join(self.data_root, self.proposal_file)
  85. proposals_list = load(
  86. self.proposal_file, backend_args=self.backend_args)
  87. assert len(self.data_list) == len(proposals_list)
  88. for data_info in self.data_list:
  89. img_path = data_info['img_path']
  90. # `file_name` is the key to obtain the proposals from the
  91. # `proposals_list`.
  92. file_name = osp.join(
  93. osp.split(osp.split(img_path)[0])[-1],
  94. osp.split(img_path)[-1])
  95. proposals = proposals_list[file_name]
  96. data_info['proposals'] = proposals
  97. def get_cat_ids(self, idx: int) -> List[int]:
  98. """Get COCO category ids by index.
  99. Args:
  100. idx (int): Index of data.
  101. Returns:
  102. List[int]: All categories in the image of specified index.
  103. """
  104. instances = self.get_data_info(idx)['instances']
  105. return [instance['bbox_label'] for instance in instances]