Added RandomZoom to preprocessing layers (#149)
* added random Zoom * added seed * update docstring * added name * added name
This commit is contained in:
parent
e56c7650e2
commit
8a355940ed
@ -77,6 +77,7 @@ from keras_core.layers.preprocessing.random_contrast import RandomContrast
|
||||
from keras_core.layers.preprocessing.random_crop import RandomCrop
|
||||
from keras_core.layers.preprocessing.random_flip import RandomFlip
|
||||
from keras_core.layers.preprocessing.random_translation import RandomTranslation
|
||||
from keras_core.layers.preprocessing.random_zoom import RandomZoom
|
||||
from keras_core.layers.preprocessing.rescaling import Rescaling
|
||||
from keras_core.layers.preprocessing.resizing import Resizing
|
||||
from keras_core.layers.preprocessing.string_lookup import StringLookup
|
||||
|
116
keras_core/layers/preprocessing/random_zoom.py
Normal file
116
keras_core/layers/preprocessing/random_zoom.py
Normal file
@ -0,0 +1,116 @@
|
||||
import numpy as np
|
||||
import tensorflow as tf
|
||||
|
||||
from keras_core import backend
|
||||
from keras_core.api_export import keras_core_export
|
||||
from keras_core.layers.layer import Layer
|
||||
|
||||
|
||||
@keras_core_export("keras_core.layers.RandomZoom")
|
||||
class RandomZoom(Layer):
|
||||
"""A preprocessing layer which randomly zooms images during training.
|
||||
|
||||
This layer will randomly zoom in or out on each axis of an image
|
||||
independently, filling empty space according to `fill_mode`.
|
||||
|
||||
Input pixel values can be of any range (e.g. `[0., 1.)` or `[0, 255]`) and
|
||||
of integer or floating point dtype.
|
||||
By default, the layer will output floats.
|
||||
|
||||
Args:
|
||||
height_factor: a float represented as fraction of value,
|
||||
or a tuple of size 2 representing lower and upper bound
|
||||
for zooming vertically. When represented as a single float,
|
||||
this value is used for both the upper and
|
||||
lower bound. A positive value means zooming out,
|
||||
while a negative value
|
||||
means zooming in. For instance, `height_factor=(0.2, 0.3)`
|
||||
result in an output zoomed out by a random amount
|
||||
in the range `[+20%, +30%]`.
|
||||
`height_factor=(-0.3, -0.2)` result in an output zoomed
|
||||
in by a random amount in the range `[+20%, +30%]`.
|
||||
width_factor: a float represented as fraction of value,
|
||||
or a tuple of size 2 representing lower and upper bound
|
||||
for zooming horizontally. When
|
||||
represented as a single float, this value is used
|
||||
for both the upper and
|
||||
lower bound. For instance, `width_factor=(0.2, 0.3)`
|
||||
result in an output
|
||||
zooming out between 20% to 30%.
|
||||
`width_factor=(-0.3, -0.2)` result in an
|
||||
output zooming in between 20% to 30%. `None` means
|
||||
i.e., zooming vertical and horizontal directions
|
||||
by preserving the aspect ratio. Defaults to `None`.
|
||||
fill_mode: Points outside the boundaries of the input are
|
||||
filled according to the given mode
|
||||
(one of `{"constant", "reflect", "wrap", "nearest"}`).
|
||||
- *reflect*: `(d c b a | a b c d | d c b a)`
|
||||
The input is extended by reflecting about
|
||||
the edge of the last pixel.
|
||||
- *constant*: `(k k k k | a b c d | k k k k)`
|
||||
The input is extended by filling all values beyond
|
||||
the edge with the same constant value k = 0.
|
||||
- *wrap*: `(a b c d | a b c d | a b c d)` The input is extended by
|
||||
wrapping around to the opposite edge.
|
||||
- *nearest*: `(a a a a | a b c d | d d d d)`
|
||||
The input is extended by the nearest pixel.
|
||||
interpolation: Interpolation mode. Supported values: `"nearest"`,
|
||||
`"bilinear"`.
|
||||
seed: Integer. Used to create a random seed.
|
||||
fill_value: a float represents the value to be filled outside
|
||||
the boundaries when `fill_mode="constant"`.
|
||||
|
||||
Example:
|
||||
|
||||
>>> input_img = np.random.random((32, 224, 224, 3))
|
||||
>>> layer = keras_core.layers.RandomZoom(.5, .2)
|
||||
>>> out_img = layer(input_img)
|
||||
|
||||
Input shape:
|
||||
3D (unbatched) or 4D (batched) tensor with shape:
|
||||
`(..., height, width, channels)`, in `"channels_last"` format.
|
||||
|
||||
Output shape:
|
||||
3D (unbatched) or 4D (batched) tensor with shape:
|
||||
`(..., height, width, channels)`, in `"channels_last"` format.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
height_factor,
|
||||
width_factor=None,
|
||||
fill_mode="reflect",
|
||||
interpolation="bilinear",
|
||||
seed=None,
|
||||
fill_value=0.0,
|
||||
name=None,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(name=name, **kwargs)
|
||||
self.seed = seed or backend.random.make_default_seed()
|
||||
self.layer = tf.keras.layers.RandomZoom(
|
||||
height_factor=height_factor,
|
||||
width_factor=width_factor,
|
||||
fill_mode=fill_mode,
|
||||
interpolation=interpolation,
|
||||
seed=self.seed,
|
||||
name=name,
|
||||
fill_value=fill_value,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def call(self, inputs, training=True):
|
||||
if not isinstance(inputs, (tf.Tensor, np.ndarray, list, tuple)):
|
||||
inputs = tf.convert_to_tensor(np.array(inputs))
|
||||
outputs = self.layer.call(inputs)
|
||||
if backend.backend() != "tensorflow":
|
||||
outputs = backend.convert_to_tensor(outputs)
|
||||
return outputs
|
||||
|
||||
def compute_output_shape(self, input_shape):
|
||||
return tuple(self.layer.compute_output_shape(input_shape))
|
||||
|
||||
def get_config(self):
|
||||
config = self.layer.get_config()
|
||||
config.update({"seed": self.seed})
|
||||
return config
|
83
keras_core/layers/preprocessing/random_zoom_test.py
Normal file
83
keras_core/layers/preprocessing/random_zoom_test.py
Normal file
@ -0,0 +1,83 @@
|
||||
import numpy as np
|
||||
from absl.testing import parameterized
|
||||
|
||||
from keras_core import backend
|
||||
from keras_core import layers
|
||||
from keras_core import testing
|
||||
|
||||
|
||||
class RandomZoomTest(testing.TestCase, parameterized.TestCase):
|
||||
@parameterized.named_parameters(
|
||||
("random_zoom_in_4_by_6", -0.4, -0.6),
|
||||
("random_zoom_in_2_by_3", -0.2, -0.3),
|
||||
("random_zoom_in_tuple_factor", (-0.4, -0.5), (-0.2, -0.3)),
|
||||
("random_zoom_out_4_by_6", 0.4, 0.6),
|
||||
("random_zoom_out_2_by_3", 0.2, 0.3),
|
||||
("random_zoom_out_tuple_factor", (0.4, 0.5), (0.2, 0.3)),
|
||||
)
|
||||
def test_random_zoom(self, height_factor, width_factor):
|
||||
self.run_layer_test(
|
||||
layers.RandomZoom,
|
||||
init_kwargs={
|
||||
"height_factor": height_factor,
|
||||
"width_factor": width_factor,
|
||||
},
|
||||
input_shape=(2, 3, 4),
|
||||
expected_output_shape=(2, 3, 4),
|
||||
supports_masking=False,
|
||||
)
|
||||
|
||||
def test_random_zoom_out_correctness(self):
|
||||
input_image = np.reshape(np.arange(0, 25), (1, 5, 5, 1))
|
||||
expected_output = np.asarray(
|
||||
[
|
||||
[0, 0, 0, 0, 0],
|
||||
[0, 5, 7, 9, 0],
|
||||
[0, 10, 12, 14, 0],
|
||||
[0, 20, 22, 24, 0],
|
||||
[0, 0, 0, 0, 0],
|
||||
]
|
||||
)
|
||||
expected_output = backend.convert_to_tensor(
|
||||
np.reshape(expected_output, (1, 5, 5, 1))
|
||||
)
|
||||
self.run_layer_test(
|
||||
layers.RandomZoom,
|
||||
init_kwargs={
|
||||
"height_factor": (0.5, 0.5),
|
||||
"width_factor": (0.8, 0.8),
|
||||
"interpolation": "nearest",
|
||||
"fill_mode": "constant",
|
||||
},
|
||||
input_shape=None,
|
||||
input_data=input_image,
|
||||
expected_output=expected_output,
|
||||
supports_masking=False,
|
||||
)
|
||||
|
||||
def test_random_zoom_in_correctness(self):
|
||||
input_image = np.reshape(np.arange(0, 25), (1, 5, 5, 1))
|
||||
expected_output = np.asarray(
|
||||
[
|
||||
[6, 7, 7, 8, 8],
|
||||
[11, 12, 12, 13, 13],
|
||||
[11, 12, 12, 13, 13],
|
||||
[16, 17, 17, 18, 18],
|
||||
[16, 17, 17, 18, 18],
|
||||
]
|
||||
)
|
||||
expected_output = backend.convert_to_tensor(
|
||||
np.reshape(expected_output, (1, 5, 5, 1))
|
||||
)
|
||||
self.run_layer_test(
|
||||
layers.RandomZoom,
|
||||
init_kwargs={
|
||||
"height_factor": (-0.5, -0.5),
|
||||
"width_factor": (-0.5, -0.5),
|
||||
"interpolation": "nearest",
|
||||
},
|
||||
input_shape=None,
|
||||
input_data=input_image,
|
||||
expected_output=expected_output,
|
||||
supports_masking=False,
|
||||
)
|
Loading…
Reference in New Issue
Block a user