Skip to content

Commit

Permalink
Added RandomScale transform (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
ternaus committed Aug 7, 2018
1 parent 78528d9 commit 9c658e5
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 1 deletion.
7 changes: 7 additions & 0 deletions albumentations/augmentations/functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ def rotate(img, angle, interpolation=cv2.INTER_LINEAR, border_mode=cv2.BORDER_RE
return img


def scale(img, scale, interpolation=cv2.INTER_LINEAR):
height, width = img.shape[:2]
new_height, new_width = int(height * scale), int(height * scale)
img = cv2.resize(img, (new_width, new_height), interpolation=interpolation)
return img


def shift_scale_rotate(img, angle, scale, dx, dy, interpolation=cv2.INTER_LINEAR, border_mode=cv2.BORDER_REFLECT_101):
height, width = img.shape[:2]
center = (width / 2, height / 2)
Expand Down
32 changes: 31 additions & 1 deletion albumentations/augmentations/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
'RandomRotate90', 'Rotate', 'ShiftScaleRotate', 'CenterCrop', 'OpticalDistortion', 'GridDistortion',
'ElasticTransform', 'HueSaturationValue', 'PadIfNeeded', 'RGBShift', 'RandomBrightness', 'RandomContrast',
'MotionBlur', 'MedianBlur', 'GaussNoise', 'CLAHE', 'ChannelShuffle', 'InvertImg', 'ToGray',
'JpegCompression', 'Cutout', 'ToFloat', 'FromFloat', 'Crop']
'JpegCompression', 'Cutout', 'ToFloat', 'FromFloat', 'Crop', 'RandomScale']


class PadIfNeeded(DualTransform):
Expand Down Expand Up @@ -212,6 +212,36 @@ def get_params(self):
return {'angle': np.random.uniform(self.limit[0], self.limit[1])}


class RandomScale(DualTransform):
"""Randomly resizes. Output image size is different from the input image size.
Args:
scale_limit ((float, float) or float): scaling factor range. If scale_limit is a single float value, the
range will be (-scale_limit, scale_limit). Default: 0.1.
interpolation (OpenCV flag): flag that is used to specify the interpolation algorithm. Should be one of:
cv2.INTER_NEAREST, cv2.INTER_LINEAR, cv2.INTER_CUBIC, cv2.INTER_AREA, cv2.INTER_LANCZOS4.
Default: cv2.INTER_LINEAR.
p (float): probability of applying the transform. Default: 0.5.
Targets:
image, mask
Image types:
uint8, float32
"""

def __init__(self, scale_limit=0.1, p=0.5, interpolation=cv2.INTER_LINEAR):
super(RandomScale, self).__init__(p)
self.scale_limit = to_tuple(scale_limit)
self.interpolation = interpolation

def apply(self, img, scale=0, interpolation=cv2.INTER_LINEAR, **params):
return F.scale(img, scale, interpolation)

def get_params(self):
return {'scale': np.random.uniform(1 + self.scale_limit[0], 1 + self.scale_limit[1])}


class ShiftScaleRotate(DualTransform):
"""Randomly applies affine transforms: translates, scales and rotates the input.
Expand Down
19 changes: 19 additions & 0 deletions tests/test_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,25 @@ def test_from_float_with_max_value_specified(max_value):
assert_array_almost_equal_nulp(F.from_float(img, dtype=np.uint32, max_value=max_value), expected)


@pytest.mark.parametrize('target', ['image', 'mask'])
def test_scale_rotate(target):
img = np.array([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]], dtype=np.uint8)
expected = np.array([[1, 1, 2, 3, 3, 4],
[3, 4, 4, 5, 6, 6],
[5, 6, 7, 7, 8, 8],
[8, 9, 9, 10, 11, 11],
[11, 12, 12, 13, 14, 14],
[13, 13, 14, 15, 15, 16]], dtype=np.uint8)

img, expected = convert_2d_to_target_format([img, expected], target=target)
scaled = F.scale(img, scale=1.5, interpolation=cv2.INTER_LINEAR)
assert np.array_equal(scaled, expected)


def test_from_float_unknown_dtype():
img = np.ones((100, 100, 3), dtype=np.float32)
with pytest.raises(RuntimeError) as exc_info:
Expand Down

0 comments on commit 9c658e5

Please sign in to comment.