-
Notifications
You must be signed in to change notification settings - Fork 332
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
Split RandomlyResizedCrop into two API surfaces (RandomlyZoomedCrop, RandomCropAndResize) #738
Merged
Merged
Changes from 3 commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
9d36b7a
Sync
AdityaKane2001 815a3ac
Merge branch 'RRC_changes' of https://github.com/AdityaKane2001/keras…
AdityaKane2001 b897f34
Added zoom factor to RRC
AdityaKane2001 108b299
Used tf.shape
AdityaKane2001 6a2e98f
dtype mismatch
AdityaKane2001 decd1eb
Debugging...
AdityaKane2001 c4bf999
Debugging...
AdityaKane2001 f1d6bb4
Fix example
LukeWood 7139540
RRC uses preprocessing.transform now
AdityaKane2001 19de16f
Merge branch 'RRC_changes' of https://github.com/AdityaKane2001/keras…
AdityaKane2001 972cdcb
Minor error
AdityaKane2001 4aef55a
Minor bug
AdityaKane2001 9eacdc4
minor issue
AdityaKane2001 1981928
minor issue
AdityaKane2001 a3158fd
minor bug
AdityaKane2001 bd8bbca
Merge branch 'master' into RRC_changes
AdityaKane2001 f40f3a5
Added unit tests
AdityaKane2001 61c336c
Merge branch 'RRC_changes' of https://github.com/AdityaKane2001/keras…
AdityaKane2001 849e40f
Fix serialization test
LukeWood b53182e
KerasCV simclr api update
LukeWood 76d87fc
Augmenter
LukeWood 1bc3fd5
Augmenter
LukeWood ec8cb71
serialization test
LukeWood a733fff
serialization test
LukeWood d7be66f
fix failing test
LukeWood 8cb5149
Split RRC API into two layers
LukeWood e35b008
Split RRC API into two layers
LukeWood 06b0cd7
Format serialization_test
LukeWood 1385228
Implemented bounding box support
AdityaKane2001 9acc024
Add preprocessing
LukeWood 900e9fb
serialization test
LukeWood 1d7d2e8
serialization test
LukeWood f2093b5
serialization test
LukeWood bc26727
RandomCropAndResize in SimCLR
LukeWood 7880d17
RandomCropAndResize in SimCLR
LukeWood ee8871e
Update examples
LukeWood 55bbb14
Update examples
LukeWood 2f132ab
Update examples
LukeWood 8d0f425
Update target_size
LukeWood File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,26 +25,19 @@ | |
class RandomResizedCrop(BaseImageAugmentationLayer): | ||
"""Randomly crops a part of an image and resizes it to provided size. | ||
|
||
This implementation takes an intuitive approach, where we crop the images to a | ||
random height and width, and then resize them. To do this, we first sample a | ||
random value for area using `crop_area_factor` and a value for aspect ratio using | ||
`aspect_ratio_factor`. Further we get the new height and width by | ||
dividing and multiplying the old height and width by the random area | ||
respectively. We then sample offsets for height and width and clip them such | ||
that the cropped area does not exceed image boundaries. Finally we do the | ||
actual cropping operation and resize the image to `target_size`. | ||
This implementation takes a distortion-oriented approach, which means the | ||
amount of distortion in the image is proportional to the `zoom_factor` | ||
argument. To do this, we first sample a random value for `zoom_factor` and | ||
`aspect_ratio_factor`. Further we deduce a `crop_size` which abides by the | ||
calculated aspect ratio. Finally we do the actual cropping operation and | ||
resize the image to `target_size`. | ||
|
||
Args: | ||
target_size: A tuple of two integers used as the target size to ultimately crop | ||
images to. | ||
crop_area_factor: A tuple of two floats, ConstantFactorSampler or | ||
UniformFactorSampler. The ratio of area of the cropped part to | ||
that of original image is sampled using this factor. Represents the | ||
lower and upper bounds for the area relative to the original image | ||
of the cropped image before resizing it to `target_size`. For | ||
self-supervised pretraining a common value for this parameter is | ||
`(0.08, 1.0)`. For fine tuning and classification a common value for this | ||
is `0.8, 1.0`. | ||
zoom_factor: A tuple of two floats, ConstantFactorSampler or | ||
UniformFactorSampler. Represents the area relative to the original image | ||
of the cropped image before resizing it to `target_size`. | ||
aspect_ratio_factor: A tuple of two floats, ConstantFactorSampler or | ||
UniformFactorSampler. Aspect ratio means the ratio of width to | ||
height of the cropped image. In the context of this layer, the aspect ratio | ||
|
@@ -60,15 +53,15 @@ class RandomResizedCrop(BaseImageAugmentationLayer): | |
def __init__( | ||
self, | ||
target_size, | ||
crop_area_factor, | ||
zoom_factor, | ||
aspect_ratio_factor, | ||
interpolation="bilinear", | ||
seed=None, | ||
**kwargs, | ||
): | ||
super().__init__(seed=seed, **kwargs) | ||
|
||
self._check_class_arguments(target_size, crop_area_factor, aspect_ratio_factor) | ||
self._check_class_arguments(target_size, zoom_factor, aspect_ratio_factor) | ||
|
||
self.target_size = target_size | ||
self.aspect_ratio_factor = preprocessing.parse_factor( | ||
|
@@ -78,10 +71,11 @@ def __init__( | |
param_name="aspect_ratio_factor", | ||
seed=seed, | ||
) | ||
self.crop_area_factor = preprocessing.parse_factor( | ||
crop_area_factor, | ||
max_value=1.0, | ||
param_name="crop_area_factor", | ||
self.zoom_factor = preprocessing.parse_factor( | ||
zoom_factor, | ||
min_value=0.0, | ||
max_value=None, | ||
param_name="zoom_factor", | ||
seed=seed, | ||
) | ||
|
||
|
@@ -91,32 +85,52 @@ def __init__( | |
def get_random_transformation( | ||
self, image=None, label=None, bounding_box=None, **kwargs | ||
): | ||
crop_area_factor = self.crop_area_factor() | ||
zoom_factor = self.zoom_factor() | ||
aspect_ratio = self.aspect_ratio_factor() | ||
|
||
new_height = tf.clip_by_value( | ||
tf.sqrt(crop_area_factor / aspect_ratio), 0.0, 1.0 | ||
) # to avoid unwanted/unintuitive effects | ||
new_width = tf.clip_by_value(tf.sqrt(crop_area_factor * aspect_ratio), 0.0, 1.0) | ||
if image.shape.rank == 3: | ||
AdityaKane2001 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
original_height = image.shape[0] | ||
original_width = image.shape[1] | ||
elif image.shape.rank == 4: | ||
original_height = image.shape[1] | ||
original_width = image.shape[2] | ||
|
||
crop_size = ( | ||
tf.round(self.target_size[0] / zoom_factor), | ||
tf.round(self.target_size[1] / zoom_factor), | ||
) | ||
|
||
new_height = crop_size[0] / tf.sqrt(aspect_ratio) | ||
|
||
new_width = crop_size[1] * tf.sqrt(aspect_ratio) | ||
|
||
new_height, new_width = self._get_corrected_crop_dimensions( | ||
new_height, new_width, original_height, original_width | ||
) | ||
|
||
new_height_ratio = new_height / original_height | ||
new_width_ratio = new_width / original_width | ||
|
||
height_offset = self._random_generator.random_uniform( | ||
(), | ||
minval=tf.minimum(0.0, 1.0 - new_height), | ||
maxval=tf.maximum(0.0, 1.0 - new_height), | ||
minval=tf.minimum(0.0, 1.0 - new_height_ratio), | ||
maxval=tf.maximum(0.0, 1.0 - new_height_ratio), | ||
dtype=tf.float32, | ||
) | ||
|
||
width_offset = self._random_generator.random_uniform( | ||
(), | ||
minval=tf.minimum(0.0, 1.0 - new_width), | ||
maxval=tf.maximum(0.0, 1.0 - new_width), | ||
minval=tf.minimum(0.0, 1.0 - new_width_ratio), | ||
maxval=tf.maximum(0.0, 1.0 - new_width_ratio), | ||
dtype=tf.float32, | ||
) | ||
|
||
# these are all values between 0 and 1 | ||
|
||
y1 = height_offset | ||
y2 = height_offset + new_height | ||
y2 = height_offset + new_height_ratio | ||
x1 = width_offset | ||
x2 = width_offset + new_width | ||
x2 = width_offset + new_width_ratio | ||
|
||
return [[y1, x1, y2, x2]] | ||
|
||
|
@@ -149,14 +163,41 @@ def augment_image(self, image, transformation, **kwargs): | |
|
||
return tf.squeeze(augmented_image, axis=0) | ||
|
||
def _get_corrected_crop_dimensions( | ||
self, new_height, new_width, original_height, original_width | ||
): | ||
if new_height > original_height and new_width > original_width: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we add some comments to justify each case? Just to improve maintainability |
||
if new_width >= new_height: | ||
new_height = (original_width / new_width) * new_height | ||
new_width = original_width | ||
else: | ||
new_width = (original_height / new_height) * new_width | ||
new_height = original_height | ||
|
||
if new_height < original_height and new_width > original_width: | ||
if new_width >= new_height: | ||
new_width = (original_height / new_height) * new_width | ||
new_height = original_height | ||
else: | ||
new_height = (original_width / new_width) * new_height | ||
new_width = original_width | ||
|
||
if new_height > original_height and new_width < original_width: | ||
if new_width >= new_height: | ||
new_width = (original_height / new_height) * new_width | ||
new_height = original_height | ||
else: | ||
new_height = (original_width / new_width) * new_height | ||
new_width = original_width | ||
|
||
return new_height, new_width | ||
|
||
def _resize(self, image): | ||
outputs = tf.keras.preprocessing.image.smart_resize(image, self.target_size) | ||
# smart_resize will always output float32, so we need to re-cast. | ||
return tf.cast(outputs, self.compute_dtype) | ||
|
||
def _check_class_arguments( | ||
self, target_size, crop_area_factor, aspect_ratio_factor | ||
): | ||
def _check_class_arguments(self, target_size, zoom_factor, aspect_ratio_factor): | ||
if ( | ||
not isinstance(target_size, (tuple, list)) | ||
or len(target_size) != 2 | ||
|
@@ -170,14 +211,14 @@ def _check_class_arguments( | |
) | ||
|
||
if ( | ||
not isinstance(crop_area_factor, (tuple, list, core.FactorSampler)) | ||
or isinstance(crop_area_factor, float) | ||
or isinstance(crop_area_factor, int) | ||
not isinstance(zoom_factor, (tuple, list, core.FactorSampler)) | ||
or isinstance(zoom_factor, float) | ||
or isinstance(zoom_factor, int) | ||
): | ||
raise ValueError( | ||
"`crop_area_factor` must be tuple of two positive floats less than " | ||
"or equal to 1 or keras_cv.core.FactorSampler instance. Received " | ||
f"crop_area_factor={crop_area_factor}" | ||
"`zoom_factor` must be tuple of two positive floats" | ||
" or keras_cv.core.FactorSampler instance. Received " | ||
f"zoom_factor={zoom_factor}" | ||
) | ||
|
||
if ( | ||
|
@@ -199,7 +240,7 @@ def get_config(self): | |
config.update( | ||
{ | ||
"target_size": self.target_size, | ||
"crop_area_factor": self.crop_area_factor, | ||
"zoom_factor": self.zoom_factor, | ||
"aspect_ratio_factor": self.aspect_ratio_factor, | ||
"interpolation": self.interpolation, | ||
"seed": self.seed, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probable error in the docstring:
The amount of distorsion is proportional to aspect_ratio_factor, not the zoom_factor. Distorsion means changing the aspect ratio, not zooming.