| | |
| |
|
| | 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') |
| |
|