Skip to content

MaskDropout augmentation (augmentations.dropout.mask_dropout)

class MaskDropout (max_objects=(1, 1), image_fill_value=0, mask_fill_value=0, always_apply=None, p=0.5) [view source on GitHub]

Image & mask augmentation that zero out mask and image regions corresponding to randomly chosen object instance from mask.

Mask must be single-channel image, zero values treated as background. Image can be any number of channels.

Parameters:

Name Type Description
max_objects Union[int, Tuple[int, int]]

Maximum number of labels that can be zeroed out. Can be tuple, in this case it's [min, max]

image_fill_value Union[float, typing_extensions.Literal['inpaint']]

Fill value to use when filling image. Can be 'inpaint' to apply inpainting (works only for 3-channel images)

mask_fill_value Union[int, float]

Fill value to use when filling mask.

Targets

image, mask

Image types: uint8, float32

Interactive Tool Available!

Explore this transform visually and adjust parameters interactively using this tool:

Open Tool

Source code in albumentations/augmentations/dropout/mask_dropout.py
Python
class MaskDropout(DualTransform):
    """Image & mask augmentation that zero out mask and image regions corresponding
    to randomly chosen object instance from mask.

    Mask must be single-channel image, zero values treated as background.
    Image can be any number of channels.

    Args:
        max_objects: Maximum number of labels that can be zeroed out. Can be tuple, in this case it's [min, max]
        image_fill_value: Fill value to use when filling image.
            Can be 'inpaint' to apply inpainting (works only  for 3-channel images)
        mask_fill_value: Fill value to use when filling mask.

    Targets:
        image, mask

    Image types:
        uint8, float32

    Reference:
        https://www.kaggle.com/c/severstal-steel-defect-detection/discussion/114254

    """

    _targets = (Targets.IMAGE, Targets.MASK)

    class InitSchema(BaseTransformInitSchema):
        max_objects: OnePlusIntRangeType = (1, 1)

        image_fill_value: Union[float, Literal["inpaint"]] = Field(
            default=0,
            description=(
                "Fill value to use when filling image. "
                "Can be 'inpaint' to apply inpainting (works only for 3-channel images)."
            ),
        )
        mask_fill_value: float = Field(default=0, description="Fill value to use when filling mask.")

    def __init__(
        self,
        max_objects: ScaleIntType = (1, 1),
        image_fill_value: Union[float, Literal["inpaint"]] = 0,
        mask_fill_value: ScalarType = 0,
        always_apply: Optional[bool] = None,
        p: float = 0.5,
    ):
        super().__init__(always_apply, p)
        self.max_objects = cast(Tuple[int, int], max_objects)
        self.image_fill_value = image_fill_value
        self.mask_fill_value = mask_fill_value

    @property
    def targets_as_params(self) -> List[str]:
        return ["mask"]

    def get_params_dependent_on_targets(self, params: Dict[str, Any]) -> Dict[str, Any]:
        mask = params["mask"]

        label_image, num_labels = label(mask, return_num=True)

        if num_labels == 0:
            dropout_mask = None
        else:
            objects_to_drop = random.randint(self.max_objects[0], self.max_objects[1])
            objects_to_drop = min(num_labels, objects_to_drop)

            if objects_to_drop == num_labels:
                dropout_mask = mask > 0
            else:
                labels_index = random.sample(range(1, num_labels + 1), objects_to_drop)
                dropout_mask = np.zeros((mask.shape[0], mask.shape[1]), dtype=bool)
                for label_index in labels_index:
                    dropout_mask |= label_image == label_index

        params.update({"dropout_mask": dropout_mask})
        del params["mask"]
        return params

    def apply(self, img: np.ndarray, dropout_mask: np.ndarray, **params: Any) -> np.ndarray:
        if dropout_mask is None:
            return img

        if self.image_fill_value == "inpaint":
            dropout_mask = dropout_mask.astype(np.uint8)
            _, _, width, height = cv2.boundingRect(dropout_mask)
            radius = min(3, max(width, height) // 2)
            return cv2.inpaint(img, dropout_mask, radius, cv2.INPAINT_NS)

        img = img.copy()
        img[dropout_mask] = self.image_fill_value

        return img

    def apply_to_mask(self, mask: np.ndarray, dropout_mask: np.ndarray, **params: Any) -> np.ndarray:
        if dropout_mask is None:
            return mask

        mask = mask.copy()
        mask[dropout_mask] = self.mask_fill_value
        return mask

    def get_transform_init_args_names(self) -> Tuple[str, ...]:
        return "max_objects", "image_fill_value", "mask_fill_value"

    @property
    def targets(self) -> Dict[str, Callable[..., Any]]:
        return {
            "image": self.apply,
            "mask": self.apply_to_mask,
            "masks": self.apply_to_masks,
        }

targets_as_params: List[str] property readonly

Targets used to get params

apply (self, img, dropout_mask, **params)

Apply transform on image.

Source code in albumentations/augmentations/dropout/mask_dropout.py
Python
def apply(self, img: np.ndarray, dropout_mask: np.ndarray, **params: Any) -> np.ndarray:
    if dropout_mask is None:
        return img

    if self.image_fill_value == "inpaint":
        dropout_mask = dropout_mask.astype(np.uint8)
        _, _, width, height = cv2.boundingRect(dropout_mask)
        radius = min(3, max(width, height) // 2)
        return cv2.inpaint(img, dropout_mask, radius, cv2.INPAINT_NS)

    img = img.copy()
    img[dropout_mask] = self.image_fill_value

    return img

get_params_dependent_on_targets (self, params)

Returns parameters dependent on targets. Dependent target is defined in self.targets_as_params

Source code in albumentations/augmentations/dropout/mask_dropout.py
Python
def get_params_dependent_on_targets(self, params: Dict[str, Any]) -> Dict[str, Any]:
    mask = params["mask"]

    label_image, num_labels = label(mask, return_num=True)

    if num_labels == 0:
        dropout_mask = None
    else:
        objects_to_drop = random.randint(self.max_objects[0], self.max_objects[1])
        objects_to_drop = min(num_labels, objects_to_drop)

        if objects_to_drop == num_labels:
            dropout_mask = mask > 0
        else:
            labels_index = random.sample(range(1, num_labels + 1), objects_to_drop)
            dropout_mask = np.zeros((mask.shape[0], mask.shape[1]), dtype=bool)
            for label_index in labels_index:
                dropout_mask |= label_image == label_index

    params.update({"dropout_mask": dropout_mask})
    del params["mask"]
    return params

get_transform_init_args_names (self)

Returns names of arguments that are used in init method of the transform

Source code in albumentations/augmentations/dropout/mask_dropout.py
Python
def get_transform_init_args_names(self) -> Tuple[str, ...]:
    return "max_objects", "image_fill_value", "mask_fill_value"