Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update random sized crop #2235

Merged
merged 2 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 3 additions & 31 deletions albumentations/augmentations/crops/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -886,47 +886,19 @@ class InitSchema(BaseTransformInitSchema):
mask_interpolation: InterpolationType
min_max_height: OnePlusIntRangeType
w2h_ratio: Annotated[float, Field(gt=0)]
width: int | None
height: int | None
size: ScaleIntType | None

@model_validator(mode="after")
def process(self) -> Self:
if isinstance(self.size, int):
if isinstance(self.width, int):
warn(
"Initializing with 'size' as an integer and a separate 'width', `height` are deprecated. "
"Please use a tuple (height, width) for the 'size' argument.",
DeprecationWarning,
stacklevel=2,
)
self.size = (self.size, self.width)
else:
msg = "If size is an integer, width as integer must be specified."
raise TypeError(msg)

if self.size is None:
if self.height is None or self.width is None:
message = "If 'size' is not provided, both 'height' and 'width' must be specified."
raise ValueError(message)
self.size = (self.height, self.width)
return self
size: tuple[int, int]

def __init__(
self,
min_max_height: tuple[int, int],
# NOTE @zetyquickly: when (width, height) are deprecated, make 'size' non optional
size: ScaleIntType | None = None,
width: int | None = None,
height: int | None = None,
*,
size: tuple[int, int],
w2h_ratio: float = 1.0,
interpolation: int = cv2.INTER_LINEAR,
mask_interpolation: int = cv2.INTER_NEAREST,
p: float = 1.0,
):
super().__init__(
size=cast(tuple[int, int], size),
size=size,
interpolation=interpolation,
mask_interpolation=mask_interpolation,
p=p,
Expand Down
2 changes: 1 addition & 1 deletion tests/aug_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
[A.RandomCrop, {"height": 90, "width": 95}],
[A.AtLeastOneBBoxRandomCrop, {"height": 90, "width": 95}],
[A.CropNonEmptyMaskIfExists, {"height": 10, "width": 10}],
[A.RandomSizedCrop, {"min_max_height": (90, 100), "height": 90, "width": 90}],
[A.RandomSizedCrop, {"min_max_height": (90, 100), "size": (90, 90)}],
[A.Crop, {"x_max": 64, "y_max": 64}],
[A.ToFloat, {"max_value": 16536}],
[
Expand Down
81 changes: 0 additions & 81 deletions tests/test_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,40 +51,6 @@
["augmentation_cls", "params"],
get_transforms(
custom_arguments={
A.Crop: {"y_min": 0, "x_min": 0, "y_max": 10, "x_max": 10},
A.CenterCrop: {"height": 10, "width": 10},
A.CropNonEmptyMaskIfExists: {"height": 10, "width": 10},
A.RandomCrop: {"height": 10, "width": 10},
A.AtLeastOneBBoxRandomCrop: {"height": 10, "width": 10},
A.RandomResizedCrop: {"size": (10, 10)},
A.RandomSizedCrop: {"min_max_height": (4, 8), "size": (10, 10)},
A.CropAndPad: {"px": 10},
A.Resize: {"height": 10, "width": 10},
A.XYMasking: {
"num_masks_x": (1, 3),
"num_masks_y": 3,
"mask_x_length": (10, 20),
"mask_y_length": 10,
"fill_mask": 1,
"fill": 0,
},
A.PadIfNeeded: {
"min_height": 512,
"min_width": 512,
"border_mode": 0,
"fill": [124, 116, 104],
"position": "top_left",
},
A.GlassBlur: dict(sigma=0.8, max_delta=5, iterations=3, mode="exact"),
A.GridDropout: dict(
ratio=0.75,
unit_size_range=(2, 10),
unit_size_max=10,
shift_xy=(10, 20),
random_offset=True,
fill=10,
fill_mask=20,
),
},
except_augmentations={
A.FDA,
Expand Down Expand Up @@ -227,38 +193,17 @@ def test_augmentations_serialization_to_file_with_custom_parameters(
["augmentation_cls", "params"],
get_2d_transforms(
custom_arguments={
A.Crop: {"y_min": 0, "y_max": 10, "x_min": 0, "x_max": 10},
A.CenterCrop: {"height": 10, "width": 10},
A.RandomCrop: {"height": 10, "width": 10},
A.AtLeastOneBBoxRandomCrop: {"height": 10, "width": 10},
A.RandomResizedCrop: {"height": 10, "width": 10},
A.RandomSizedCrop: {"min_max_height": (4, 8), "height": 10, "width": 10},
A.CropAndPad: {"px": 10},
A.Resize: {"height": 10, "width": 10},
A.RandomSizedBBoxSafeCrop: {"height": 10, "width": 10},
A.BBoxSafeRandomCrop: {"erosion_rate": 0.6},
A.PadIfNeeded: {
"min_height": 512,
"min_width": 512,
"border_mode": 0,
"value": [124, 116, 104],
"position": "top_left",
},
A.GridElasticDeform: {"num_grid_xy": (10, 10), "magnitude": 10},
},
except_augmentations={
A.FDA,
A.HistogramMatching,
A.PixelDistributionAdaptation,
A.Lambda,
A.CoarseDropout,
A.OpticalDistortion,
A.TemplateTransform,
A.XYMasking,
A.CropNonEmptyMaskIfExists,
A.OverlayElements,
A.TextImage,
A.PadIfNeeded3D,
},
),
)
Expand Down Expand Up @@ -297,39 +242,13 @@ def test_augmentations_for_bboxes_serialization(
["augmentation_cls", "params"],
get_2d_transforms(
custom_arguments={
A.Crop: {"y_min": 0, "y_max": 10, "x_min": 0, "x_max": 10},
A.CenterCrop: {"height": 10, "width": 10},
A.CropNonEmptyMaskIfExists: {"height": 10, "width": 10},
A.RandomCrop: {"height": 10, "width": 10},
A.AtLeastOneBBoxRandomCrop: {"height": 10, "width": 10},
A.RandomResizedCrop: {"height": 10, "width": 10},
A.RandomSizedCrop: {"min_max_height": (4, 8), "height": 10, "width": 10},
A.CropAndPad: {"px": 10},
A.Resize: {"height": 10, "width": 10},
A.XYMasking: {
"num_masks_x": (1, 3),
"num_masks_y": 3,
"mask_x_length": (10, 20),
"mask_y_length": 10,
"fill": 0,
"fill_mask": 1,
},
A.PadIfNeeded: {
"min_height": 512,
"min_width": 512,
"border_mode": 0,
"fill": [124, 116, 104],
"position": "top_left",
},
A.GridElasticDeform: {"num_grid_xy": (10, 10), "magnitude": 10},
},
except_augmentations={
A.FDA,
A.HistogramMatching,
A.PixelDistributionAdaptation,
A.Lambda,
A.CropNonEmptyMaskIfExists,
A.OpticalDistortion,
A.RandomSizedBBoxSafeCrop,
A.BBoxSafeRandomCrop,
A.TemplateTransform,
Expand Down
4 changes: 2 additions & 2 deletions tests/test_targets.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ def test_image_only(augmentation_cls, params):
A.CropNonEmptyMaskIfExists: {"height": 10, "width": 10},
A.RandomCrop: {"height": 10, "width": 10},
A.AtLeastOneBBoxRandomCrop: {"height": 10, "width": 10},
A.RandomResizedCrop: {"height": 10, "width": 10},
A.RandomSizedCrop: {"min_max_height": (4, 8), "height": 10, "width": 10},
A.RandomResizedCrop: {"size": (10, 10)},
A.RandomSizedCrop: {"min_max_height": (4, 8), "size": (10, 10)},
A.RandomSizedBBoxSafeCrop: {"height": 10, "width": 10},
A.CropAndPad: {"px": 10},
A.Resize: {"height": 10, "width": 10},
Expand Down
58 changes: 4 additions & 54 deletions tests/test_transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,20 +189,18 @@ def test_force_apply():
A.Compose(
[
A.RandomSizedCrop(
min_max_height=(256, 1025), height=512, width=512, p=1
min_max_height=(256, 1025), size=(512, 512), p=1
),
A.OneOf(
[
A.RandomSizedCrop(
min_max_height=(256, 512),
height=384,
width=384,
size=(384, 384),
p=0.5,
),
A.RandomSizedCrop(
min_max_height=(256, 512),
height=512,
width=512,
size=(512, 512),
p=0.5,
),
],
Expand All @@ -212,7 +210,7 @@ def test_force_apply():
A.Compose(
[
A.RandomSizedCrop(
min_max_height=(256, 1025), height=256, width=256, p=1
min_max_height=(256, 1025), size=(256, 256), p=1
),
A.OneOf([A.HueSaturationValue(p=0.5), A.RGBShift(p=0.7)], p=1),
],
Expand Down Expand Up @@ -1080,54 +1078,6 @@ def test_non_rgb_transform_warning(augmentation, img_channels):
assert str(exc_info.value).startswith(message)


@pytest.mark.parametrize("height, width", [(100, 200), (200, 100)])
@pytest.mark.parametrize("scale", [(0.08, 1.0), (0.5, 1.0)])
@pytest.mark.parametrize("ratio", [(0.75, 1.33), (1.0, 1.0)])
def test_random_crop_interfaces_vs_torchvision(height, width, scale, ratio):
# NOTE: below will fail when height, width is no longer expected as first two positional arguments
transform_albu = A.RandomResizedCrop(height, width, scale=scale, ratio=ratio, p=1)
transform_albu_new = A.RandomResizedCrop(
size=(height, width), scale=scale, ratio=ratio, p=1
)

image = np.random.randint(0, 256, (224, 224, 3), dtype=np.uint8)
transformed_image_albu = transform_albu(image=image)["image"]
transformed_image_albu_new = transform_albu_new(image=image)["image"]

# PyTorch equivalent operation
transform_pt = torch_transforms.RandomResizedCrop(
size=(height, width), scale=scale, ratio=ratio
)
image_pil = torch_transforms.functional.to_pil_image(image)
transformed_image_pt = transform_pt(image_pil)

transformed_image_pt_np = np.array(transformed_image_pt)
assert transformed_image_albu.shape == transformed_image_pt_np.shape
assert transformed_image_albu_new.shape == transformed_image_pt_np.shape

# NOTE: below will fail when height, width is no longer expected as second and third positional arguments
transform_albu = A.RandomSizedCrop((128, 224), height, width, p=1.0)
transform_albu_new = A.RandomSizedCrop(
min_max_height=(128, 224), size=(height, width), p=1.0
)
transformed_image_albu = transform_albu(image=image)["image"]
transformed_image_albu_new = transform_albu_new(image=image)["image"]
assert transformed_image_albu.shape == transformed_image_pt_np.shape
assert transformed_image_albu_new.shape == transformed_image_pt_np.shape

# NOTE: below will fail when height, width is no longer expected as first two positional arguments
transform_albu = A.RandomResizedCrop(height, width, scale=scale, ratio=ratio, p=1)
transform_albu_height_is_size = A.RandomResizedCrop(
size=height, width=width, scale=scale, ratio=ratio, p=1
)

image = np.random.randint(0, 256, (224, 224, 3), dtype=np.uint8)
transformed_image_albu = transform_albu(image=image)["image"]
transform_albu_height_is_size = transform_albu_new(image=image)["image"]
assert transformed_image_albu.shape == transformed_image_pt_np.shape
assert transform_albu_height_is_size.shape == transformed_image_pt_np.shape


@pytest.mark.parametrize(
"num_shadows_limit, num_shadows_lower, num_shadows_upper, expected_warning",
[
Expand Down
Loading