Spaces:
Runtime error
Runtime error
| # Copyright (c) OpenMMLab. All rights reserved. | |
| from typing import List, Optional, Union | |
| import numpy as np | |
| from mmcv.transforms import RandomChoice | |
| from mmcv.transforms.utils import cache_randomness | |
| from mmengine.config import ConfigDict | |
| from mmdet.registry import TRANSFORMS | |
| # AutoAugment uses reinforcement learning to search for | |
| # some widely useful data augmentation strategies, | |
| # here we provide AUTOAUG_POLICIES_V0. | |
| # For AUTOAUG_POLICIES_V0, each tuple is an augmentation | |
| # operation of the form (operation, probability, magnitude). | |
| # Each element in policies is a policy that will be applied | |
| # sequentially on the image. | |
| # RandAugment defines a data augmentation search space, RANDAUG_SPACE, | |
| # sampling 1~3 data augmentations each time, and | |
| # setting the magnitude of each data augmentation randomly, | |
| # which will be applied sequentially on the image. | |
| _MAX_LEVEL = 10 | |
| AUTOAUG_POLICIES_V0 = [ | |
| [('Equalize', 0.8, 1), ('ShearY', 0.8, 4)], | |
| [('Color', 0.4, 9), ('Equalize', 0.6, 3)], | |
| [('Color', 0.4, 1), ('Rotate', 0.6, 8)], | |
| [('Solarize', 0.8, 3), ('Equalize', 0.4, 7)], | |
| [('Solarize', 0.4, 2), ('Solarize', 0.6, 2)], | |
| [('Color', 0.2, 0), ('Equalize', 0.8, 8)], | |
| [('Equalize', 0.4, 8), ('SolarizeAdd', 0.8, 3)], | |
| [('ShearX', 0.2, 9), ('Rotate', 0.6, 8)], | |
| [('Color', 0.6, 1), ('Equalize', 1.0, 2)], | |
| [('Invert', 0.4, 9), ('Rotate', 0.6, 0)], | |
| [('Equalize', 1.0, 9), ('ShearY', 0.6, 3)], | |
| [('Color', 0.4, 7), ('Equalize', 0.6, 0)], | |
| [('Posterize', 0.4, 6), ('AutoContrast', 0.4, 7)], | |
| [('Solarize', 0.6, 8), ('Color', 0.6, 9)], | |
| [('Solarize', 0.2, 4), ('Rotate', 0.8, 9)], | |
| [('Rotate', 1.0, 7), ('TranslateY', 0.8, 9)], | |
| [('ShearX', 0.0, 0), ('Solarize', 0.8, 4)], | |
| [('ShearY', 0.8, 0), ('Color', 0.6, 4)], | |
| [('Color', 1.0, 0), ('Rotate', 0.6, 2)], | |
| [('Equalize', 0.8, 4), ('Equalize', 0.0, 8)], | |
| [('Equalize', 1.0, 4), ('AutoContrast', 0.6, 2)], | |
| [('ShearY', 0.4, 7), ('SolarizeAdd', 0.6, 7)], | |
| [('Posterize', 0.8, 2), ('Solarize', 0.6, 10)], | |
| [('Solarize', 0.6, 8), ('Equalize', 0.6, 1)], | |
| [('Color', 0.8, 6), ('Rotate', 0.4, 5)], | |
| ] | |
| def policies_v0(): | |
| """Autoaugment policies that was used in AutoAugment Paper.""" | |
| policies = list() | |
| for policy_args in AUTOAUG_POLICIES_V0: | |
| policy = list() | |
| for args in policy_args: | |
| policy.append(dict(type=args[0], prob=args[1], level=args[2])) | |
| policies.append(policy) | |
| return policies | |
| RANDAUG_SPACE = [[dict(type='AutoContrast')], [dict(type='Equalize')], | |
| [dict(type='Invert')], [dict(type='Rotate')], | |
| [dict(type='Posterize')], [dict(type='Solarize')], | |
| [dict(type='SolarizeAdd')], [dict(type='Color')], | |
| [dict(type='Contrast')], [dict(type='Brightness')], | |
| [dict(type='Sharpness')], [dict(type='ShearX')], | |
| [dict(type='ShearY')], [dict(type='TranslateX')], | |
| [dict(type='TranslateY')]] | |
| def level_to_mag(level: Optional[int], min_mag: float, | |
| max_mag: float) -> float: | |
| """Map from level to magnitude.""" | |
| if level is None: | |
| return round(np.random.rand() * (max_mag - min_mag) + min_mag, 1) | |
| else: | |
| return round(level / _MAX_LEVEL * (max_mag - min_mag) + min_mag, 1) | |
| class AutoAugment(RandomChoice): | |
| """Auto augmentation. | |
| This data augmentation is proposed in `AutoAugment: Learning | |
| Augmentation Policies from Data <https://arxiv.org/abs/1805.09501>`_ | |
| and in `Learning Data Augmentation Strategies for Object Detection | |
| <https://arxiv.org/pdf/1906.11172>`_. | |
| Required Keys: | |
| - img | |
| - gt_bboxes (BaseBoxes[torch.float32]) (optional) | |
| - gt_bboxes_labels (np.int64) (optional) | |
| - gt_masks (BitmapMasks | PolygonMasks) (optional) | |
| - gt_ignore_flags (bool) (optional) | |
| - gt_seg_map (np.uint8) (optional) | |
| Modified Keys: | |
| - img | |
| - img_shape | |
| - gt_bboxes | |
| - gt_bboxes_labels | |
| - gt_masks | |
| - gt_ignore_flags | |
| - gt_seg_map | |
| Added Keys: | |
| - homography_matrix | |
| Args: | |
| policies (List[List[Union[dict, ConfigDict]]]): | |
| The policies of auto augmentation.Each policy in ``policies`` | |
| is a specific augmentation policy, and is composed by several | |
| augmentations. When AutoAugment is called, a random policy in | |
| ``policies`` will be selected to augment images. | |
| Defaults to policy_v0(). | |
| prob (list[float], optional): The probabilities associated | |
| with each policy. The length should be equal to the policy | |
| number and the sum should be 1. If not given, a uniform | |
| distribution will be assumed. Defaults to None. | |
| Examples: | |
| >>> policies = [ | |
| >>> [ | |
| >>> dict(type='Sharpness', prob=0.0, level=8), | |
| >>> dict(type='ShearX', prob=0.4, level=0,) | |
| >>> ], | |
| >>> [ | |
| >>> dict(type='Rotate', prob=0.6, level=10), | |
| >>> dict(type='Color', prob=1.0, level=6) | |
| >>> ] | |
| >>> ] | |
| >>> augmentation = AutoAugment(policies) | |
| >>> img = np.ones(100, 100, 3) | |
| >>> gt_bboxes = np.ones(10, 4) | |
| >>> results = dict(img=img, gt_bboxes=gt_bboxes) | |
| >>> results = augmentation(results) | |
| """ | |
| def __init__(self, | |
| policies: List[List[Union[dict, ConfigDict]]] = policies_v0(), | |
| prob: Optional[List[float]] = None) -> None: | |
| assert isinstance(policies, list) and len(policies) > 0, \ | |
| 'Policies must be a non-empty list.' | |
| for policy in policies: | |
| assert isinstance(policy, list) and len(policy) > 0, \ | |
| 'Each policy in policies must be a non-empty list.' | |
| for augment in policy: | |
| assert isinstance(augment, dict) and 'type' in augment, \ | |
| 'Each specific augmentation must be a dict with key' \ | |
| ' "type".' | |
| super().__init__(transforms=policies, prob=prob) | |
| self.policies = policies | |
| def __repr__(self) -> str: | |
| return f'{self.__class__.__name__}(policies={self.policies}, ' \ | |
| f'prob={self.prob})' | |
| class RandAugment(RandomChoice): | |
| """Rand augmentation. | |
| This data augmentation is proposed in `RandAugment: | |
| Practical automated data augmentation with a reduced | |
| search space <https://arxiv.org/abs/1909.13719>`_. | |
| Required Keys: | |
| - img | |
| - gt_bboxes (BaseBoxes[torch.float32]) (optional) | |
| - gt_bboxes_labels (np.int64) (optional) | |
| - gt_masks (BitmapMasks | PolygonMasks) (optional) | |
| - gt_ignore_flags (bool) (optional) | |
| - gt_seg_map (np.uint8) (optional) | |
| Modified Keys: | |
| - img | |
| - img_shape | |
| - gt_bboxes | |
| - gt_bboxes_labels | |
| - gt_masks | |
| - gt_ignore_flags | |
| - gt_seg_map | |
| Added Keys: | |
| - homography_matrix | |
| Args: | |
| aug_space (List[List[Union[dict, ConfigDict]]]): The augmentation space | |
| of rand augmentation. Each augmentation transform in ``aug_space`` | |
| is a specific transform, and is composed by several augmentations. | |
| When RandAugment is called, a random transform in ``aug_space`` | |
| will be selected to augment images. Defaults to aug_space. | |
| aug_num (int): Number of augmentation to apply equentially. | |
| Defaults to 2. | |
| prob (list[float], optional): The probabilities associated with | |
| each augmentation. The length should be equal to the | |
| augmentation space and the sum should be 1. If not given, | |
| a uniform distribution will be assumed. Defaults to None. | |
| Examples: | |
| >>> aug_space = [ | |
| >>> dict(type='Sharpness'), | |
| >>> dict(type='ShearX'), | |
| >>> dict(type='Color'), | |
| >>> ], | |
| >>> augmentation = RandAugment(aug_space) | |
| >>> img = np.ones(100, 100, 3) | |
| >>> gt_bboxes = np.ones(10, 4) | |
| >>> results = dict(img=img, gt_bboxes=gt_bboxes) | |
| >>> results = augmentation(results) | |
| """ | |
| def __init__(self, | |
| aug_space: List[Union[dict, ConfigDict]] = RANDAUG_SPACE, | |
| aug_num: int = 2, | |
| prob: Optional[List[float]] = None) -> None: | |
| assert isinstance(aug_space, list) and len(aug_space) > 0, \ | |
| 'Augmentation space must be a non-empty list.' | |
| for aug in aug_space: | |
| assert isinstance(aug, list) and len(aug) == 1, \ | |
| 'Each augmentation in aug_space must be a list.' | |
| for transform in aug: | |
| assert isinstance(transform, dict) and 'type' in transform, \ | |
| 'Each specific transform must be a dict with key' \ | |
| ' "type".' | |
| super().__init__(transforms=aug_space, prob=prob) | |
| self.aug_space = aug_space | |
| self.aug_num = aug_num | |
| def random_pipeline_index(self): | |
| indices = np.arange(len(self.transforms)) | |
| return np.random.choice( | |
| indices, self.aug_num, p=self.prob, replace=False) | |
| def transform(self, results: dict) -> dict: | |
| """Transform function to use RandAugment. | |
| Args: | |
| results (dict): Result dict from loading pipeline. | |
| Returns: | |
| dict: Result dict with RandAugment. | |
| """ | |
| for idx in self.random_pipeline_index(): | |
| results = self.transforms[idx](results) | |
| return results | |
| def __repr__(self) -> str: | |
| return f'{self.__class__.__name__}(' \ | |
| f'aug_space={self.aug_space}, '\ | |
| f'aug_num={self.aug_num}, ' \ | |
| f'prob={self.prob})' | |