Skip to content

Commit

Permalink
Add RandomCropFromBorders and support for bbox in ElasticTransform …
Browse files Browse the repository at this point in the history
…from #476 (#1240)
  • Loading branch information
Dipet committed Aug 10, 2022
1 parent 244b756 commit 46e280f
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ Spatial-level transforms will simultaneously change both an input image as well
| [PiecewiseAffine](https://albumentations.ai/docs/api_reference/augmentations/geometric/transforms/#albumentations.augmentations.geometric.transforms.PiecewiseAffine) |||||
| [PixelDropout](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.PixelDropout) |||||
| [RandomCrop](https://albumentations.ai/docs/api_reference/augmentations/crops/transforms/#albumentations.augmentations.crops.transforms.RandomCrop) |||||
| [RandomCropFromBorders](https://albumentations.ai/docs/api_reference/augmentations/crops/transforms/#albumentations.augmentations.crops.transforms.RandomCropFromBorders) |||||
| [RandomCropNearBBox](https://albumentations.ai/docs/api_reference/augmentations/crops/transforms/#albumentations.augmentations.crops.transforms.RandomCropNearBBox) |||||
| [RandomGridShuffle](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.RandomGridShuffle) ||| ||
| [RandomResizedCrop](https://albumentations.ai/docs/api_reference/augmentations/crops/transforms/#albumentations.augmentations.crops.transforms.RandomResizedCrop) |||||
Expand Down
66 changes: 66 additions & 0 deletions albumentations/augmentations/crops/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"RandomCropNearBBox",
"RandomSizedBBoxSafeCrop",
"CropAndPad",
"RandomCropFromBorders",
]


Expand Down Expand Up @@ -852,3 +853,68 @@ def get_transform_init_args_names(self) -> Tuple[str, ...]:
"sample_independently",
"interpolation",
)


class RandomCropFromBorders(DualTransform):
"""Crop bbox from image randomly cut parts from borders without resize at the end
Args:
crop_left (float): single float value in (0.0, 1.0) range. Default 0.1. Image will be randomly cut
from left side in range [0, crop_left * width)
crop_right (float): single float value in (0.0, 1.0) range. Default 0.1. Image will be randomly cut
from right side in range [(1 - crop_right) * width, width)
crop_top (float): singlefloat value in (0.0, 1.0) range. Default 0.1. Image will be randomly cut
from top side in range [0, crop_top * height)
crop_bottom (float): single float value in (0.0, 1.0) range. Default 0.1. Image will be randomly cut
from bottom side in range [(1 - crop_bottom) * height, height)
p (float): probability of applying the transform. Default: 1.
Targets:
image, mask, bboxes, keypoints
Image types:
uint8, float32
"""

def __init__(
self,
crop_left=0.1,
crop_right=0.1,
crop_top=0.1,
crop_bottom=0.1,
always_apply=False,
p=1.0,
):
super(RandomCropFromBorders, self).__init__(always_apply, p)
self.crop_left = crop_left
self.crop_right = crop_right
self.crop_top = crop_top
self.crop_bottom = crop_bottom

def get_params_dependent_on_targets(self, params):
img = params["image"]
x_min = random.randint(0, int(self.crop_left * img.shape[1]))
x_max = random.randint(max(x_min + 1, int((1 - self.crop_right) * img.shape[1])), img.shape[1])
y_min = random.randint(0, int(self.crop_top * img.shape[0]))
y_max = random.randint(max(y_min + 1, int((1 - self.crop_bottom) * img.shape[0])), img.shape[0])
return {"x_min": x_min, "x_max": x_max, "y_min": y_min, "y_max": y_max}

def apply(self, img, x_min=0, x_max=0, y_min=0, y_max=0, **params):
return F.clamping_crop(img, x_min, y_min, x_max, y_max)

def apply_to_mask(self, mask, x_min=0, x_max=0, y_min=0, y_max=0, **params):
return F.clamping_crop(mask, x_min, y_min, x_max, y_max)

def apply_to_bbox(self, bbox, x_min=0, x_max=0, y_min=0, y_max=0, **params):
rows, cols = params["rows"], params["cols"]
return F.bbox_crop(bbox, x_min, y_min, x_max, y_max, rows, cols)

def apply_to_keypoint(self, keypoint, x_min=0, x_max=0, y_min=0, y_max=0, **params):
return F.crop_keypoint_by_coords(keypoint, crop_coords=(x_min, y_min, x_max, y_max))

@property
def targets_as_params(self):
return ["image"]

def get_transform_init_args_names(self):
return "crop_left", "crop_right", "crop_top", "crop_bottom"
2 changes: 2 additions & 0 deletions tests/test_augmentations.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ def test_augmentations_wont_change_float_input(augmentation_cls, params, float_i
A.ToSepia,
A.PixelDistributionAdaptation,
A.UnsharpMask,
A.RandomCropFromBorders,
},
),
)
Expand Down Expand Up @@ -325,6 +326,7 @@ def test_augmentations_wont_change_shape_grayscale(augmentation_cls, params, ima
A.SmallestMaxSize,
A.PadIfNeeded,
A.RandomScale,
A.RandomCropFromBorders,
},
),
)
Expand Down
1 change: 1 addition & 0 deletions tests/test_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ def test_augmentations_serialization(augmentation_cls, params, p, seed, image, m
[A.AdvancedBlur, dict(blur_limit=(3, 5), rotate_limit=(60, 90))],
[A.PixelDropout, {"dropout_prob": 0.1, "per_channel": True, "drop_value": None}],
[A.PixelDropout, {"dropout_prob": 0.1, "per_channel": False, "drop_value": None, "mask_drop_value": 15}],
[A.RandomCropFromBorders, dict(crop_left=0.2, crop_right=0.3, crop_top=0.05, crop_bottom=0.5)],
]

AUGMENTATION_CLS_EXCEPT = {
Expand Down

0 comments on commit 46e280f

Please sign in to comment.