| |
|
|
| from typing import Optional, Union |
|
|
| import cv2 |
| import mmcv |
| import numpy as np |
| from mmcv.transforms import BaseTransform |
| from mmcv.transforms.utils import cache_randomness |
|
|
| from mmdet.registry import TRANSFORMS |
| from mmdet.structures.bbox import autocast_box_type |
| from .augment_wrappers import _MAX_LEVEL, level_to_mag |
|
|
|
|
| @TRANSFORMS.register_module() |
| class GeomTransform(BaseTransform): |
| """Base class for geometric transformations. All geometric transformations |
| need to inherit from this base class. ``GeomTransform`` unifies the class |
| attributes and class functions of geometric transformations (ShearX, |
| ShearY, Rotate, TranslateX, and TranslateY), and records the homography |
| matrix. |
| |
| Required Keys: |
| |
| - img |
| - gt_bboxes (BaseBoxes[torch.float32]) (optional) |
| - gt_masks (BitmapMasks | PolygonMasks) (optional) |
| - gt_seg_map (np.uint8) (optional) |
| |
| Modified Keys: |
| |
| - img |
| - gt_bboxes |
| - gt_masks |
| - gt_seg_map |
| |
| Added Keys: |
| |
| - homography_matrix |
| |
| Args: |
| prob (float): The probability for performing the geometric |
| transformation and should be in range [0, 1]. Defaults to 1.0. |
| level (int, optional): The level should be in range [0, _MAX_LEVEL]. |
| If level is None, it will generate from [0, _MAX_LEVEL] randomly. |
| Defaults to None. |
| min_mag (float): The minimum magnitude for geometric transformation. |
| Defaults to 0.0. |
| max_mag (float): The maximum magnitude for geometric transformation. |
| Defaults to 1.0. |
| reversal_prob (float): The probability that reverses the geometric |
| transformation magnitude. Should be in range [0,1]. |
| Defaults to 0.5. |
| img_border_value (int | float | tuple): The filled values for |
| image border. If float, the same fill value will be used for |
| all the three channels of image. If tuple, it should be 3 elements. |
| Defaults to 128. |
| mask_border_value (int): The fill value used for masks. Defaults to 0. |
| seg_ignore_label (int): The fill value used for segmentation map. |
| Note this value must equals ``ignore_label`` in ``semantic_head`` |
| of the corresponding config. Defaults to 255. |
| interpolation (str): Interpolation method, accepted values are |
| "nearest", "bilinear", "bicubic", "area", "lanczos" for 'cv2' |
| backend, "nearest", "bilinear" for 'pillow' backend. Defaults |
| to 'bilinear'. |
| """ |
|
|
| def __init__(self, |
| prob: float = 1.0, |
| level: Optional[int] = None, |
| min_mag: float = 0.0, |
| max_mag: float = 1.0, |
| reversal_prob: float = 0.5, |
| img_border_value: Union[int, float, tuple] = 128, |
| mask_border_value: int = 0, |
| seg_ignore_label: int = 255, |
| interpolation: str = 'bilinear') -> None: |
| assert 0 <= prob <= 1.0, f'The probability of the transformation ' \ |
| f'should be in range [0,1], got {prob}.' |
| assert level is None or isinstance(level, int), \ |
| f'The level should be None or type int, got {type(level)}.' |
| assert level is None or 0 <= level <= _MAX_LEVEL, \ |
| f'The level should be in range [0,{_MAX_LEVEL}], got {level}.' |
| assert isinstance(min_mag, float), \ |
| f'min_mag should be type float, got {type(min_mag)}.' |
| assert isinstance(max_mag, float), \ |
| f'max_mag should be type float, got {type(max_mag)}.' |
| assert min_mag <= max_mag, \ |
| f'min_mag should smaller than max_mag, ' \ |
| f'got min_mag={min_mag} and max_mag={max_mag}' |
| assert isinstance(reversal_prob, float), \ |
| f'reversal_prob should be type float, got {type(max_mag)}.' |
| assert 0 <= reversal_prob <= 1.0, \ |
| f'The reversal probability of the transformation magnitude ' \ |
| f'should be type float, got {type(reversal_prob)}.' |
| if isinstance(img_border_value, (float, int)): |
| img_border_value = tuple([float(img_border_value)] * 3) |
| elif isinstance(img_border_value, tuple): |
| assert len(img_border_value) == 3, \ |
| f'img_border_value as tuple must have 3 elements, ' \ |
| f'got {len(img_border_value)}.' |
| img_border_value = tuple([float(val) for val in img_border_value]) |
| else: |
| raise ValueError( |
| 'img_border_value must be float or tuple with 3 elements.') |
| assert np.all([0 <= val <= 255 for val in img_border_value]), 'all ' \ |
| 'elements of img_border_value should between range [0,255].' \ |
| f'got {img_border_value}.' |
| self.prob = prob |
| self.level = level |
| self.min_mag = min_mag |
| self.max_mag = max_mag |
| self.reversal_prob = reversal_prob |
| self.img_border_value = img_border_value |
| self.mask_border_value = mask_border_value |
| self.seg_ignore_label = seg_ignore_label |
| self.interpolation = interpolation |
|
|
| def _transform_img(self, results: dict, mag: float) -> None: |
| """Transform the image.""" |
| pass |
|
|
| def _transform_masks(self, results: dict, mag: float) -> None: |
| """Transform the masks.""" |
| pass |
|
|
| def _transform_seg(self, results: dict, mag: float) -> None: |
| """Transform the segmentation map.""" |
| pass |
|
|
| def _get_homography_matrix(self, results: dict, mag: float) -> np.ndarray: |
| """Get the homography matrix for the geometric transformation.""" |
| return np.eye(3, dtype=np.float32) |
|
|
| def _transform_bboxes(self, results: dict, mag: float) -> None: |
| """Transform the bboxes.""" |
| results['gt_bboxes'].project_(self.homography_matrix) |
| results['gt_bboxes'].clip_(results['img_shape']) |
|
|
| def _record_homography_matrix(self, results: dict) -> None: |
| """Record the homography matrix for the geometric transformation.""" |
| if results.get('homography_matrix', None) is None: |
| results['homography_matrix'] = self.homography_matrix |
| else: |
| results['homography_matrix'] = self.homography_matrix @ results[ |
| 'homography_matrix'] |
|
|
| @cache_randomness |
| def _random_disable(self): |
| """Randomly disable the transform.""" |
| return np.random.rand() > self.prob |
|
|
| @cache_randomness |
| def _get_mag(self): |
| """Get the magnitude of the transform.""" |
| mag = level_to_mag(self.level, self.min_mag, self.max_mag) |
| return -mag if np.random.rand() > self.reversal_prob else mag |
|
|
| @autocast_box_type() |
| def transform(self, results: dict) -> dict: |
| """Transform function for images, bounding boxes, masks and semantic |
| segmentation map. |
| |
| Args: |
| results (dict): Result dict from loading pipeline. |
| |
| Returns: |
| dict: Transformed results. |
| """ |
|
|
| if self._random_disable(): |
| return results |
| mag = self._get_mag() |
| self.homography_matrix = self._get_homography_matrix(results, mag) |
| self._record_homography_matrix(results) |
| self._transform_img(results, mag) |
| if results.get('gt_bboxes', None) is not None: |
| self._transform_bboxes(results, mag) |
| if results.get('gt_masks', None) is not None: |
| self._transform_masks(results, mag) |
| if results.get('gt_seg_map', None) is not None: |
| self._transform_seg(results, mag) |
| return results |
|
|
| def __repr__(self) -> str: |
| repr_str = self.__class__.__name__ |
| repr_str += f'(prob={self.prob}, ' |
| repr_str += f'level={self.level}, ' |
| repr_str += f'min_mag={self.min_mag}, ' |
| repr_str += f'max_mag={self.max_mag}, ' |
| repr_str += f'reversal_prob={self.reversal_prob}, ' |
| repr_str += f'img_border_value={self.img_border_value}, ' |
| repr_str += f'mask_border_value={self.mask_border_value}, ' |
| repr_str += f'seg_ignore_label={self.seg_ignore_label}, ' |
| repr_str += f'interpolation={self.interpolation})' |
| return repr_str |
|
|
|
|
| @TRANSFORMS.register_module() |
| class ShearX(GeomTransform): |
| """Shear the images, bboxes, masks and segmentation map horizontally. |
| |
| Required Keys: |
| |
| - img |
| - gt_bboxes (BaseBoxes[torch.float32]) (optional) |
| - gt_masks (BitmapMasks | PolygonMasks) (optional) |
| - gt_seg_map (np.uint8) (optional) |
| |
| Modified Keys: |
| |
| - img |
| - gt_bboxes |
| - gt_masks |
| - gt_seg_map |
| |
| Added Keys: |
| |
| - homography_matrix |
| |
| Args: |
| prob (float): The probability for performing Shear and should be in |
| range [0, 1]. Defaults to 1.0. |
| level (int, optional): The level should be in range [0, _MAX_LEVEL]. |
| If level is None, it will generate from [0, _MAX_LEVEL] randomly. |
| Defaults to None. |
| min_mag (float): The minimum angle for the horizontal shear. |
| Defaults to 0.0. |
| max_mag (float): The maximum angle for the horizontal shear. |
| Defaults to 30.0. |
| reversal_prob (float): The probability that reverses the horizontal |
| shear magnitude. Should be in range [0,1]. Defaults to 0.5. |
| img_border_value (int | float | tuple): The filled values for |
| image border. If float, the same fill value will be used for |
| all the three channels of image. If tuple, it should be 3 elements. |
| Defaults to 128. |
| mask_border_value (int): The fill value used for masks. Defaults to 0. |
| seg_ignore_label (int): The fill value used for segmentation map. |
| Note this value must equals ``ignore_label`` in ``semantic_head`` |
| of the corresponding config. Defaults to 255. |
| interpolation (str): Interpolation method, accepted values are |
| "nearest", "bilinear", "bicubic", "area", "lanczos" for 'cv2' |
| backend, "nearest", "bilinear" for 'pillow' backend. Defaults |
| to 'bilinear'. |
| """ |
|
|
| def __init__(self, |
| prob: float = 1.0, |
| level: Optional[int] = None, |
| min_mag: float = 0.0, |
| max_mag: float = 30.0, |
| reversal_prob: float = 0.5, |
| img_border_value: Union[int, float, tuple] = 128, |
| mask_border_value: int = 0, |
| seg_ignore_label: int = 255, |
| interpolation: str = 'bilinear') -> None: |
| assert 0. <= min_mag <= 90., \ |
| f'min_mag angle for ShearX should be ' \ |
| f'in range [0, 90], got {min_mag}.' |
| assert 0. <= max_mag <= 90., \ |
| f'max_mag angle for ShearX should be ' \ |
| f'in range [0, 90], got {max_mag}.' |
| super().__init__( |
| prob=prob, |
| level=level, |
| min_mag=min_mag, |
| max_mag=max_mag, |
| reversal_prob=reversal_prob, |
| img_border_value=img_border_value, |
| mask_border_value=mask_border_value, |
| seg_ignore_label=seg_ignore_label, |
| interpolation=interpolation) |
|
|
| @cache_randomness |
| def _get_mag(self): |
| """Get the magnitude of the transform.""" |
| mag = level_to_mag(self.level, self.min_mag, self.max_mag) |
| mag = np.tan(mag * np.pi / 180) |
| return -mag if np.random.rand() > self.reversal_prob else mag |
|
|
| def _get_homography_matrix(self, results: dict, mag: float) -> np.ndarray: |
| """Get the homography matrix for ShearX.""" |
| return np.array([[1, mag, 0], [0, 1, 0], [0, 0, 1]], dtype=np.float32) |
|
|
| def _transform_img(self, results: dict, mag: float) -> None: |
| """Shear the image horizontally.""" |
| results['img'] = mmcv.imshear( |
| results['img'], |
| mag, |
| direction='horizontal', |
| border_value=self.img_border_value, |
| interpolation=self.interpolation) |
|
|
| def _transform_masks(self, results: dict, mag: float) -> None: |
| """Shear the masks horizontally.""" |
| results['gt_masks'] = results['gt_masks'].shear( |
| results['img_shape'], |
| mag, |
| direction='horizontal', |
| border_value=self.mask_border_value, |
| interpolation=self.interpolation) |
|
|
| def _transform_seg(self, results: dict, mag: float) -> None: |
| """Shear the segmentation map horizontally.""" |
| results['gt_seg_map'] = mmcv.imshear( |
| results['gt_seg_map'], |
| mag, |
| direction='horizontal', |
| border_value=self.seg_ignore_label, |
| interpolation='nearest') |
|
|
|
|
| @TRANSFORMS.register_module() |
| class ShearY(GeomTransform): |
| """Shear the images, bboxes, masks and segmentation map vertically. |
| |
| Required Keys: |
| |
| - img |
| - gt_bboxes (BaseBoxes[torch.float32]) (optional) |
| - gt_masks (BitmapMasks | PolygonMasks) (optional) |
| - gt_seg_map (np.uint8) (optional) |
| |
| Modified Keys: |
| |
| - img |
| - gt_bboxes |
| - gt_masks |
| - gt_seg_map |
| |
| Added Keys: |
| |
| - homography_matrix |
| |
| Args: |
| prob (float): The probability for performing ShearY and should be in |
| range [0, 1]. Defaults to 1.0. |
| level (int, optional): The level should be in range [0,_MAX_LEVEL]. |
| If level is None, it will generate from [0, _MAX_LEVEL] randomly. |
| Defaults to None. |
| min_mag (float): The minimum angle for the vertical shear. |
| Defaults to 0.0. |
| max_mag (float): The maximum angle for the vertical shear. |
| Defaults to 30.0. |
| reversal_prob (float): The probability that reverses the vertical |
| shear magnitude. Should be in range [0,1]. Defaults to 0.5. |
| img_border_value (int | float | tuple): The filled values for |
| image border. If float, the same fill value will be used for |
| all the three channels of image. If tuple, it should be 3 elements. |
| Defaults to 128. |
| mask_border_value (int): The fill value used for masks. Defaults to 0. |
| seg_ignore_label (int): The fill value used for segmentation map. |
| Note this value must equals ``ignore_label`` in ``semantic_head`` |
| of the corresponding config. Defaults to 255. |
| interpolation (str): Interpolation method, accepted values are |
| "nearest", "bilinear", "bicubic", "area", "lanczos" for 'cv2' |
| backend, "nearest", "bilinear" for 'pillow' backend. Defaults |
| to 'bilinear'. |
| """ |
|
|
| def __init__(self, |
| prob: float = 1.0, |
| level: Optional[int] = None, |
| min_mag: float = 0.0, |
| max_mag: float = 30., |
| reversal_prob: float = 0.5, |
| img_border_value: Union[int, float, tuple] = 128, |
| mask_border_value: int = 0, |
| seg_ignore_label: int = 255, |
| interpolation: str = 'bilinear') -> None: |
| assert 0. <= min_mag <= 90., \ |
| f'min_mag angle for ShearY should be ' \ |
| f'in range [0, 90], got {min_mag}.' |
| assert 0. <= max_mag <= 90., \ |
| f'max_mag angle for ShearY should be ' \ |
| f'in range [0, 90], got {max_mag}.' |
| super().__init__( |
| prob=prob, |
| level=level, |
| min_mag=min_mag, |
| max_mag=max_mag, |
| reversal_prob=reversal_prob, |
| img_border_value=img_border_value, |
| mask_border_value=mask_border_value, |
| seg_ignore_label=seg_ignore_label, |
| interpolation=interpolation) |
|
|
| @cache_randomness |
| def _get_mag(self): |
| """Get the magnitude of the transform.""" |
| mag = level_to_mag(self.level, self.min_mag, self.max_mag) |
| mag = np.tan(mag * np.pi / 180) |
| return -mag if np.random.rand() > self.reversal_prob else mag |
|
|
| def _get_homography_matrix(self, results: dict, mag: float) -> np.ndarray: |
| """Get the homography matrix for ShearY.""" |
| return np.array([[1, 0, 0], [mag, 1, 0], [0, 0, 1]], dtype=np.float32) |
|
|
| def _transform_img(self, results: dict, mag: float) -> None: |
| """Shear the image vertically.""" |
| results['img'] = mmcv.imshear( |
| results['img'], |
| mag, |
| direction='vertical', |
| border_value=self.img_border_value, |
| interpolation=self.interpolation) |
|
|
| def _transform_masks(self, results: dict, mag: float) -> None: |
| """Shear the masks vertically.""" |
| results['gt_masks'] = results['gt_masks'].shear( |
| results['img_shape'], |
| mag, |
| direction='vertical', |
| border_value=self.mask_border_value, |
| interpolation=self.interpolation) |
|
|
| def _transform_seg(self, results: dict, mag: float) -> None: |
| """Shear the segmentation map vertically.""" |
| results['gt_seg_map'] = mmcv.imshear( |
| results['gt_seg_map'], |
| mag, |
| direction='vertical', |
| border_value=self.seg_ignore_label, |
| interpolation='nearest') |
|
|
|
|
| @TRANSFORMS.register_module() |
| class Rotate(GeomTransform): |
| """Rotate the images, bboxes, masks and segmentation map. |
| |
| Required Keys: |
| |
| - img |
| - gt_bboxes (BaseBoxes[torch.float32]) (optional) |
| - gt_masks (BitmapMasks | PolygonMasks) (optional) |
| - gt_seg_map (np.uint8) (optional) |
| |
| Modified Keys: |
| |
| - img |
| - gt_bboxes |
| - gt_masks |
| - gt_seg_map |
| |
| Added Keys: |
| |
| - homography_matrix |
| |
| Args: |
| prob (float): The probability for perform transformation and |
| should be in range 0 to 1. Defaults to 1.0. |
| level (int, optional): The level should be in range [0, _MAX_LEVEL]. |
| If level is None, it will generate from [0, _MAX_LEVEL] randomly. |
| Defaults to None. |
| min_mag (float): The maximum angle for rotation. |
| Defaults to 0.0. |
| max_mag (float): The maximum angle for rotation. |
| Defaults to 30.0. |
| reversal_prob (float): The probability that reverses the rotation |
| magnitude. Should be in range [0,1]. Defaults to 0.5. |
| img_border_value (int | float | tuple): The filled values for |
| image border. If float, the same fill value will be used for |
| all the three channels of image. If tuple, it should be 3 elements. |
| Defaults to 128. |
| mask_border_value (int): The fill value used for masks. Defaults to 0. |
| seg_ignore_label (int): The fill value used for segmentation map. |
| Note this value must equals ``ignore_label`` in ``semantic_head`` |
| of the corresponding config. Defaults to 255. |
| interpolation (str): Interpolation method, accepted values are |
| "nearest", "bilinear", "bicubic", "area", "lanczos" for 'cv2' |
| backend, "nearest", "bilinear" for 'pillow' backend. Defaults |
| to 'bilinear'. |
| """ |
|
|
| def __init__(self, |
| prob: float = 1.0, |
| level: Optional[int] = None, |
| min_mag: float = 0.0, |
| max_mag: float = 30.0, |
| reversal_prob: float = 0.5, |
| img_border_value: Union[int, float, tuple] = 128, |
| mask_border_value: int = 0, |
| seg_ignore_label: int = 255, |
| interpolation: str = 'bilinear') -> None: |
| assert 0. <= min_mag <= 180., \ |
| f'min_mag for Rotate should be in range [0,180], got {min_mag}.' |
| assert 0. <= max_mag <= 180., \ |
| f'max_mag for Rotate should be in range [0,180], got {max_mag}.' |
| super().__init__( |
| prob=prob, |
| level=level, |
| min_mag=min_mag, |
| max_mag=max_mag, |
| reversal_prob=reversal_prob, |
| img_border_value=img_border_value, |
| mask_border_value=mask_border_value, |
| seg_ignore_label=seg_ignore_label, |
| interpolation=interpolation) |
|
|
| def _get_homography_matrix(self, results: dict, mag: float) -> np.ndarray: |
| """Get the homography matrix for Rotate.""" |
| img_shape = results['img_shape'] |
| center = ((img_shape[1] - 1) * 0.5, (img_shape[0] - 1) * 0.5) |
| cv2_rotation_matrix = cv2.getRotationMatrix2D(center, -mag, 1.0) |
| return np.concatenate( |
| [cv2_rotation_matrix, |
| np.array([0, 0, 1]).reshape((1, 3))]).astype(np.float32) |
|
|
| def _transform_img(self, results: dict, mag: float) -> None: |
| """Rotate the image.""" |
| results['img'] = mmcv.imrotate( |
| results['img'], |
| mag, |
| border_value=self.img_border_value, |
| interpolation=self.interpolation) |
|
|
| def _transform_masks(self, results: dict, mag: float) -> None: |
| """Rotate the masks.""" |
| results['gt_masks'] = results['gt_masks'].rotate( |
| results['img_shape'], |
| mag, |
| border_value=self.mask_border_value, |
| interpolation=self.interpolation) |
|
|
| def _transform_seg(self, results: dict, mag: float) -> None: |
| """Rotate the segmentation map.""" |
| results['gt_seg_map'] = mmcv.imrotate( |
| results['gt_seg_map'], |
| mag, |
| border_value=self.seg_ignore_label, |
| interpolation='nearest') |
|
|
|
|
| @TRANSFORMS.register_module() |
| class TranslateX(GeomTransform): |
| """Translate the images, bboxes, masks and segmentation map horizontally. |
| |
| Required Keys: |
| |
| - img |
| - gt_bboxes (BaseBoxes[torch.float32]) (optional) |
| - gt_masks (BitmapMasks | PolygonMasks) (optional) |
| - gt_seg_map (np.uint8) (optional) |
| |
| Modified Keys: |
| |
| - img |
| - gt_bboxes |
| - gt_masks |
| - gt_seg_map |
| |
| Added Keys: |
| |
| - homography_matrix |
| |
| Args: |
| prob (float): The probability for perform transformation and |
| should be in range 0 to 1. Defaults to 1.0. |
| level (int, optional): The level should be in range [0, _MAX_LEVEL]. |
| If level is None, it will generate from [0, _MAX_LEVEL] randomly. |
| Defaults to None. |
| min_mag (float): The minimum pixel's offset ratio for horizontal |
| translation. Defaults to 0.0. |
| max_mag (float): The maximum pixel's offset ratio for horizontal |
| translation. Defaults to 0.1. |
| reversal_prob (float): The probability that reverses the horizontal |
| translation magnitude. Should be in range [0,1]. Defaults to 0.5. |
| img_border_value (int | float | tuple): The filled values for |
| image border. If float, the same fill value will be used for |
| all the three channels of image. If tuple, it should be 3 elements. |
| Defaults to 128. |
| mask_border_value (int): The fill value used for masks. Defaults to 0. |
| seg_ignore_label (int): The fill value used for segmentation map. |
| Note this value must equals ``ignore_label`` in ``semantic_head`` |
| of the corresponding config. Defaults to 255. |
| interpolation (str): Interpolation method, accepted values are |
| "nearest", "bilinear", "bicubic", "area", "lanczos" for 'cv2' |
| backend, "nearest", "bilinear" for 'pillow' backend. Defaults |
| to 'bilinear'. |
| """ |
|
|
| def __init__(self, |
| prob: float = 1.0, |
| level: Optional[int] = None, |
| min_mag: float = 0.0, |
| max_mag: float = 0.1, |
| reversal_prob: float = 0.5, |
| img_border_value: Union[int, float, tuple] = 128, |
| mask_border_value: int = 0, |
| seg_ignore_label: int = 255, |
| interpolation: str = 'bilinear') -> None: |
| assert 0. <= min_mag <= 1., \ |
| f'min_mag ratio for TranslateX should be ' \ |
| f'in range [0, 1], got {min_mag}.' |
| assert 0. <= max_mag <= 1., \ |
| f'max_mag ratio for TranslateX should be ' \ |
| f'in range [0, 1], got {max_mag}.' |
| super().__init__( |
| prob=prob, |
| level=level, |
| min_mag=min_mag, |
| max_mag=max_mag, |
| reversal_prob=reversal_prob, |
| img_border_value=img_border_value, |
| mask_border_value=mask_border_value, |
| seg_ignore_label=seg_ignore_label, |
| interpolation=interpolation) |
|
|
| def _get_homography_matrix(self, results: dict, mag: float) -> np.ndarray: |
| """Get the homography matrix for TranslateX.""" |
| mag = int(results['img_shape'][1] * mag) |
| return np.array([[1, 0, mag], [0, 1, 0], [0, 0, 1]], dtype=np.float32) |
|
|
| def _transform_img(self, results: dict, mag: float) -> None: |
| """Translate the image horizontally.""" |
| mag = int(results['img_shape'][1] * mag) |
| results['img'] = mmcv.imtranslate( |
| results['img'], |
| mag, |
| direction='horizontal', |
| border_value=self.img_border_value, |
| interpolation=self.interpolation) |
|
|
| def _transform_masks(self, results: dict, mag: float) -> None: |
| """Translate the masks horizontally.""" |
| mag = int(results['img_shape'][1] * mag) |
| results['gt_masks'] = results['gt_masks'].translate( |
| results['img_shape'], |
| mag, |
| direction='horizontal', |
| border_value=self.mask_border_value, |
| interpolation=self.interpolation) |
|
|
| def _transform_seg(self, results: dict, mag: float) -> None: |
| """Translate the segmentation map horizontally.""" |
| mag = int(results['img_shape'][1] * mag) |
| results['gt_seg_map'] = mmcv.imtranslate( |
| results['gt_seg_map'], |
| mag, |
| direction='horizontal', |
| border_value=self.seg_ignore_label, |
| interpolation='nearest') |
|
|
|
|
| @TRANSFORMS.register_module() |
| class TranslateY(GeomTransform): |
| """Translate the images, bboxes, masks and segmentation map vertically. |
| |
| Required Keys: |
| |
| - img |
| - gt_bboxes (BaseBoxes[torch.float32]) (optional) |
| - gt_masks (BitmapMasks | PolygonMasks) (optional) |
| - gt_seg_map (np.uint8) (optional) |
| |
| Modified Keys: |
| |
| - img |
| - gt_bboxes |
| - gt_masks |
| - gt_seg_map |
| |
| Added Keys: |
| |
| - homography_matrix |
| |
| Args: |
| prob (float): The probability for perform transformation and |
| should be in range 0 to 1. Defaults to 1.0. |
| level (int, optional): The level should be in range [0, _MAX_LEVEL]. |
| If level is None, it will generate from [0, _MAX_LEVEL] randomly. |
| Defaults to None. |
| min_mag (float): The minimum pixel's offset ratio for vertical |
| translation. Defaults to 0.0. |
| max_mag (float): The maximum pixel's offset ratio for vertical |
| translation. Defaults to 0.1. |
| reversal_prob (float): The probability that reverses the vertical |
| translation magnitude. Should be in range [0,1]. Defaults to 0.5. |
| img_border_value (int | float | tuple): The filled values for |
| image border. If float, the same fill value will be used for |
| all the three channels of image. If tuple, it should be 3 elements. |
| Defaults to 128. |
| mask_border_value (int): The fill value used for masks. Defaults to 0. |
| seg_ignore_label (int): The fill value used for segmentation map. |
| Note this value must equals ``ignore_label`` in ``semantic_head`` |
| of the corresponding config. Defaults to 255. |
| interpolation (str): Interpolation method, accepted values are |
| "nearest", "bilinear", "bicubic", "area", "lanczos" for 'cv2' |
| backend, "nearest", "bilinear" for 'pillow' backend. Defaults |
| to 'bilinear'. |
| """ |
|
|
| def __init__(self, |
| prob: float = 1.0, |
| level: Optional[int] = None, |
| min_mag: float = 0.0, |
| max_mag: float = 0.1, |
| reversal_prob: float = 0.5, |
| img_border_value: Union[int, float, tuple] = 128, |
| mask_border_value: int = 0, |
| seg_ignore_label: int = 255, |
| interpolation: str = 'bilinear') -> None: |
| assert 0. <= min_mag <= 1., \ |
| f'min_mag ratio for TranslateY should be ' \ |
| f'in range [0,1], got {min_mag}.' |
| assert 0. <= max_mag <= 1., \ |
| f'max_mag ratio for TranslateY should be ' \ |
| f'in range [0,1], got {max_mag}.' |
| super().__init__( |
| prob=prob, |
| level=level, |
| min_mag=min_mag, |
| max_mag=max_mag, |
| reversal_prob=reversal_prob, |
| img_border_value=img_border_value, |
| mask_border_value=mask_border_value, |
| seg_ignore_label=seg_ignore_label, |
| interpolation=interpolation) |
|
|
| def _get_homography_matrix(self, results: dict, mag: float) -> np.ndarray: |
| """Get the homography matrix for TranslateY.""" |
| mag = int(results['img_shape'][0] * mag) |
| return np.array([[1, 0, 0], [0, 1, mag], [0, 0, 1]], dtype=np.float32) |
|
|
| def _transform_img(self, results: dict, mag: float) -> None: |
| """Translate the image vertically.""" |
| mag = int(results['img_shape'][0] * mag) |
| results['img'] = mmcv.imtranslate( |
| results['img'], |
| mag, |
| direction='vertical', |
| border_value=self.img_border_value, |
| interpolation=self.interpolation) |
|
|
| def _transform_masks(self, results: dict, mag: float) -> None: |
| """Translate masks vertically.""" |
| mag = int(results['img_shape'][0] * mag) |
| results['gt_masks'] = results['gt_masks'].translate( |
| results['img_shape'], |
| mag, |
| direction='vertical', |
| border_value=self.mask_border_value, |
| interpolation=self.interpolation) |
|
|
| def _transform_seg(self, results: dict, mag: float) -> None: |
| """Translate segmentation map vertically.""" |
| mag = int(results['img_shape'][0] * mag) |
| results['gt_seg_map'] = mmcv.imtranslate( |
| results['gt_seg_map'], |
| mag, |
| direction='vertical', |
| border_value=self.seg_ignore_label, |
| interpolation='nearest') |
|
|