Skip to content
15 changes: 14 additions & 1 deletion keras/src/layers/preprocessing/image_preprocessing/resizing.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,27 @@ def __init__(
self.width_axis = -2

def transform_images(self, images, transformation=None, training=True):
# Compute effective crop flag:
# only crop if aspect ratios differ and flag is True
input_height, input_width = transformation
source_aspect_ratio = input_width / input_height
target_aspect_ratio = self.width / self.height
Comment on lines +107 to +108
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

To prevent a potential ZeroDivisionError if input_height or self.height is zero, it's safer to add a small epsilon to the denominators. This is a good defensive practice, especially since these values could be dynamic tensors.

Suggested change
source_aspect_ratio = input_width / input_height
target_aspect_ratio = self.width / self.height
source_aspect_ratio = input_width / (input_height + self.backend.epsilon())
target_aspect_ratio = self.width / (self.height + self.backend.epsilon())

# Use a small epsilon for floating-point comparison
aspect_ratios_match = (
abs(source_aspect_ratio - target_aspect_ratio) < 1e-6
)
effective_crop_to_aspect_ratio = (
self.crop_to_aspect_ratio and not aspect_ratios_match
)

size = (self.height, self.width)
resized = self.backend.image.resize(
images,
size=size,
interpolation=self.interpolation,
antialias=self.antialias,
data_format=self.data_format,
crop_to_aspect_ratio=self.crop_to_aspect_ratio,
crop_to_aspect_ratio=effective_crop_to_aspect_ratio,
pad_to_aspect_ratio=self.pad_to_aspect_ratio,
fill_mode=self.fill_mode,
fill_value=self.fill_value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,31 @@ def test_crop_to_aspect_ratio(self, data_format):
ref_out = ref_out.transpose(0, 3, 1, 2)
self.assertAllClose(ref_out, out)

@parameterized.parameters([("channels_first",), ("channels_last",)])
def test_crop_to_aspect_ratio_no_op_when_aspects_match(self, data_format):
# Test that crop_to_aspect_ratio=True behaves identically to False
# when source and target aspect ratios match (no cropping should occur).
img = np.reshape(np.arange(0, 16), (1, 4, 4, 1)).astype("float32")
if data_format == "channels_first":
img = img.transpose(0, 3, 1, 2)
out_false = layers.Resizing(
height=2,
width=2,
interpolation="nearest",
data_format=data_format,
crop_to_aspect_ratio=False,
)(img)
out_true = layers.Resizing(
height=2,
width=2,
interpolation="nearest",
data_format=data_format,
crop_to_aspect_ratio=True,
)(img)
# Outputs should be identical when aspect ratios match
# (4:4 -> 2:2, both 1:1).
self.assertAllClose(out_false, out_true)

@parameterized.parameters([("channels_first",), ("channels_last",)])
def test_unbatched_image(self, data_format):
img = np.reshape(np.arange(0, 16), (4, 4, 1)).astype("float32")
Expand Down