| | |
| | import warnings |
| | from typing import Optional |
| |
|
| | import mmengine.fileio as fileio |
| | import numpy as np |
| |
|
| | import mmcv |
| | from .base import BaseTransform |
| | from .builder import TRANSFORMS |
| |
|
| |
|
| | @TRANSFORMS.register_module() |
| | class LoadImageFromFile(BaseTransform): |
| | """Load an image from file. |
| | |
| | Required Keys: |
| | |
| | - img_path |
| | |
| | Modified Keys: |
| | |
| | - img |
| | - img_shape |
| | - ori_shape |
| | |
| | Args: |
| | to_float32 (bool): Whether to convert the loaded image to a float32 |
| | numpy array. If set to False, the loaded image is an uint8 array. |
| | Defaults to False. |
| | color_type (str): The flag argument for :func:`mmcv.imfrombytes`. |
| | Defaults to 'color'. |
| | imdecode_backend (str): The image decoding backend type. The backend |
| | argument for :func:`mmcv.imfrombytes`. |
| | See :func:`mmcv.imfrombytes` for details. |
| | Defaults to 'cv2'. |
| | file_client_args (dict, optional): Arguments to instantiate a |
| | FileClient. See :class:`mmengine.fileio.FileClient` for details. |
| | Defaults to None. It will be deprecated in future. Please use |
| | ``backend_args`` instead. |
| | Deprecated in version 2.0.0rc4. |
| | ignore_empty (bool): Whether to allow loading empty image or file path |
| | not existent. Defaults to False. |
| | backend_args (dict, optional): Instantiates the corresponding file |
| | backend. It may contain `backend` key to specify the file |
| | backend. If it contains, the file backend corresponding to this |
| | value will be used and initialized with the remaining values, |
| | otherwise the corresponding file backend will be selected |
| | based on the prefix of the file path. Defaults to None. |
| | New in version 2.0.0rc4. |
| | """ |
| |
|
| | def __init__(self, |
| | to_float32: bool = False, |
| | color_type: str = 'color', |
| | imdecode_backend: str = 'cv2', |
| | file_client_args: Optional[dict] = None, |
| | ignore_empty: bool = False, |
| | *, |
| | backend_args: Optional[dict] = None) -> None: |
| | self.ignore_empty = ignore_empty |
| | self.to_float32 = to_float32 |
| | self.color_type = color_type |
| | self.imdecode_backend = imdecode_backend |
| |
|
| | self.file_client_args: Optional[dict] = None |
| | self.backend_args: Optional[dict] = None |
| | if file_client_args is not None: |
| | warnings.warn( |
| | '"file_client_args" will be deprecated in future. ' |
| | 'Please use "backend_args" instead', DeprecationWarning) |
| | if backend_args is not None: |
| | raise ValueError( |
| | '"file_client_args" and "backend_args" cannot be set ' |
| | 'at the same time.') |
| |
|
| | self.file_client_args = file_client_args.copy() |
| | if backend_args is not None: |
| | self.backend_args = backend_args.copy() |
| |
|
| | def transform(self, results: dict) -> Optional[dict]: |
| | """Functions to load image. |
| | |
| | Args: |
| | results (dict): Result dict from |
| | :class:`mmengine.dataset.BaseDataset`. |
| | |
| | Returns: |
| | dict: The dict contains loaded image and meta information. |
| | """ |
| |
|
| | filename = results['img_path'] |
| | try: |
| | if self.file_client_args is not None: |
| | file_client = fileio.FileClient.infer_client( |
| | self.file_client_args, filename) |
| | img_bytes = file_client.get(filename) |
| | else: |
| | img_bytes = fileio.get( |
| | filename, backend_args=self.backend_args) |
| | img = mmcv.imfrombytes( |
| | img_bytes, flag=self.color_type, backend=self.imdecode_backend) |
| | except Exception as e: |
| | if self.ignore_empty: |
| | return None |
| | else: |
| | raise e |
| | |
| | |
| | assert img is not None, f'failed to load image: {filename}' |
| | if self.to_float32: |
| | img = img.astype(np.float32) |
| |
|
| | results['img'] = img |
| | results['img_shape'] = img.shape[:2] |
| | results['ori_shape'] = img.shape[:2] |
| | return results |
| |
|
| | def __repr__(self): |
| | repr_str = (f'{self.__class__.__name__}(' |
| | f'ignore_empty={self.ignore_empty}, ' |
| | f'to_float32={self.to_float32}, ' |
| | f"color_type='{self.color_type}', " |
| | f"imdecode_backend='{self.imdecode_backend}', ") |
| |
|
| | if self.file_client_args is not None: |
| | repr_str += f'file_client_args={self.file_client_args})' |
| | else: |
| | repr_str += f'backend_args={self.backend_args})' |
| |
|
| | return repr_str |
| |
|
| |
|
| | @TRANSFORMS.register_module() |
| | class LoadAnnotations(BaseTransform): |
| | """Load and process the ``instances`` and ``seg_map`` annotation provided |
| | by dataset. |
| | |
| | The annotation format is as the following: |
| | |
| | .. code-block:: python |
| | |
| | { |
| | 'instances': |
| | [ |
| | { |
| | # List of 4 numbers representing the bounding box of the |
| | # instance, in (x1, y1, x2, y2) order. |
| | 'bbox': [x1, y1, x2, y2], |
| | |
| | # Label of image classification. |
| | 'bbox_label': 1, |
| | |
| | # Used in key point detection. |
| | # Can only load the format of [x1, y1, v1,…, xn, yn, vn]. v[i] |
| | # means the visibility of this keypoint. n must be equal to the |
| | # number of keypoint categories. |
| | 'keypoints': [x1, y1, v1, ..., xn, yn, vn] |
| | } |
| | ] |
| | # Filename of semantic or panoptic segmentation ground truth file. |
| | 'seg_map_path': 'a/b/c' |
| | } |
| | |
| | After this module, the annotation has been changed to the format below: |
| | |
| | .. code-block:: python |
| | |
| | { |
| | # In (x1, y1, x2, y2) order, float type. N is the number of bboxes |
| | # in np.float32 |
| | 'gt_bboxes': np.ndarray(N, 4) |
| | # In np.int64 type. |
| | 'gt_bboxes_labels': np.ndarray(N, ) |
| | # In uint8 type. |
| | 'gt_seg_map': np.ndarray (H, W) |
| | # with (x, y, v) order, in np.float32 type. |
| | 'gt_keypoints': np.ndarray(N, NK, 3) |
| | } |
| | |
| | Required Keys: |
| | |
| | - instances |
| | |
| | - bbox (optional) |
| | - bbox_label |
| | - keypoints (optional) |
| | |
| | - seg_map_path (optional) |
| | |
| | Added Keys: |
| | |
| | - gt_bboxes (np.float32) |
| | - gt_bboxes_labels (np.int64) |
| | - gt_seg_map (np.uint8) |
| | - gt_keypoints (np.float32) |
| | |
| | Args: |
| | with_bbox (bool): Whether to parse and load the bbox annotation. |
| | Defaults to True. |
| | with_label (bool): Whether to parse and load the label annotation. |
| | Defaults to True. |
| | with_seg (bool): Whether to parse and load the semantic segmentation |
| | annotation. Defaults to False. |
| | with_keypoints (bool): Whether to parse and load the keypoints |
| | annotation. Defaults to False. |
| | imdecode_backend (str): The image decoding backend type. The backend |
| | argument for :func:`mmcv.imfrombytes`. |
| | See :func:`mmcv.imfrombytes` for details. |
| | Defaults to 'cv2'. |
| | file_client_args (dict, optional): Arguments to instantiate a |
| | FileClient. See :class:`mmengine.fileio.FileClient` for details. |
| | Defaults to None. It will be deprecated in future. Please use |
| | ``backend_args`` instead. |
| | Deprecated in version 2.0.0rc4. |
| | backend_args (dict, optional): Instantiates the corresponding file |
| | backend. It may contain `backend` key to specify the file |
| | backend. If it contains, the file backend corresponding to this |
| | value will be used and initialized with the remaining values, |
| | otherwise the corresponding file backend will be selected |
| | based on the prefix of the file path. Defaults to None. |
| | New in version 2.0.0rc4. |
| | """ |
| |
|
| | def __init__( |
| | self, |
| | with_bbox: bool = True, |
| | with_label: bool = True, |
| | with_seg: bool = False, |
| | with_keypoints: bool = False, |
| | imdecode_backend: str = 'cv2', |
| | file_client_args: Optional[dict] = None, |
| | *, |
| | backend_args: Optional[dict] = None, |
| | ) -> None: |
| | super().__init__() |
| | self.with_bbox = with_bbox |
| | self.with_label = with_label |
| | self.with_seg = with_seg |
| | self.with_keypoints = with_keypoints |
| | self.imdecode_backend = imdecode_backend |
| |
|
| | self.file_client_args: Optional[dict] = None |
| | self.backend_args: Optional[dict] = None |
| | if file_client_args is not None: |
| | warnings.warn( |
| | '"file_client_args" will be deprecated in future. ' |
| | 'Please use "backend_args" instead', DeprecationWarning) |
| | if backend_args is not None: |
| | raise ValueError( |
| | '"file_client_args" and "backend_args" cannot be set ' |
| | 'at the same time.') |
| |
|
| | self.file_client_args = file_client_args.copy() |
| | if backend_args is not None: |
| | self.backend_args = backend_args.copy() |
| |
|
| | def _load_bboxes(self, results: dict) -> None: |
| | """Private function to load bounding box annotations. |
| | |
| | Args: |
| | results (dict): Result dict from |
| | :class:`mmengine.dataset.BaseDataset`. |
| | |
| | Returns: |
| | dict: The dict contains loaded bounding box annotations. |
| | """ |
| | gt_bboxes = [] |
| | for instance in results['instances']: |
| | gt_bboxes.append(instance['bbox']) |
| | results['gt_bboxes'] = np.array( |
| | gt_bboxes, dtype=np.float32).reshape(-1, 4) |
| |
|
| | def _load_labels(self, results: dict) -> None: |
| | """Private function to load label annotations. |
| | |
| | Args: |
| | results (dict): Result dict from |
| | :class:`mmengine.dataset.BaseDataset`. |
| | |
| | Returns: |
| | dict: The dict contains loaded label annotations. |
| | """ |
| | gt_bboxes_labels = [] |
| | for instance in results['instances']: |
| | gt_bboxes_labels.append(instance['bbox_label']) |
| | results['gt_bboxes_labels'] = np.array( |
| | gt_bboxes_labels, dtype=np.int64) |
| |
|
| | def _load_seg_map(self, results: dict) -> None: |
| | """Private function to load semantic segmentation annotations. |
| | |
| | Args: |
| | results (dict): Result dict from |
| | :class:`mmengine.dataset.BaseDataset`. |
| | |
| | Returns: |
| | dict: The dict contains loaded semantic segmentation annotations. |
| | """ |
| | if self.file_client_args is not None: |
| | file_client = fileio.FileClient.infer_client( |
| | self.file_client_args, results['seg_map_path']) |
| | img_bytes = file_client.get(results['seg_map_path']) |
| | else: |
| | img_bytes = fileio.get( |
| | results['seg_map_path'], backend_args=self.backend_args) |
| |
|
| | results['gt_seg_map'] = mmcv.imfrombytes( |
| | img_bytes, flag='unchanged', |
| | backend=self.imdecode_backend).squeeze() |
| |
|
| | def _load_kps(self, results: dict) -> None: |
| | """Private function to load keypoints annotations. |
| | |
| | Args: |
| | results (dict): Result dict from |
| | :class:`mmengine.dataset.BaseDataset`. |
| | |
| | Returns: |
| | dict: The dict contains loaded keypoints annotations. |
| | """ |
| | gt_keypoints = [] |
| | for instance in results['instances']: |
| | gt_keypoints.append(instance['keypoints']) |
| | results['gt_keypoints'] = np.array(gt_keypoints, np.float32).reshape( |
| | (len(gt_keypoints), -1, 3)) |
| |
|
| | def transform(self, results: dict) -> dict: |
| | """Function to load multiple types annotations. |
| | |
| | Args: |
| | results (dict): Result dict from |
| | :class:`mmengine.dataset.BaseDataset`. |
| | |
| | Returns: |
| | dict: The dict contains loaded bounding box, label and |
| | semantic segmentation and keypoints annotations. |
| | """ |
| |
|
| | if self.with_bbox: |
| | self._load_bboxes(results) |
| | if self.with_label: |
| | self._load_labels(results) |
| | if self.with_seg: |
| | self._load_seg_map(results) |
| | if self.with_keypoints: |
| | self._load_kps(results) |
| | return results |
| |
|
| | def __repr__(self) -> str: |
| | repr_str = self.__class__.__name__ |
| | repr_str += f'(with_bbox={self.with_bbox}, ' |
| | repr_str += f'with_label={self.with_label}, ' |
| | repr_str += f'with_seg={self.with_seg}, ' |
| | repr_str += f'with_keypoints={self.with_keypoints}, ' |
| | repr_str += f"imdecode_backend='{self.imdecode_backend}', " |
| |
|
| | if self.file_client_args is not None: |
| | repr_str += f'file_client_args={self.file_client_args})' |
| | else: |
| | repr_str += f'backend_args={self.backend_args})' |
| |
|
| | return repr_str |
| |
|