lambdawaff
lambdawaff

Reputation: 141

Is there an equivalent to PyTorch's RandomResizedCrop in Tensorflow?

Torchvision's RandomResizedCrop is a tool I've found to be extremely handy when I'm working with datasets of high-resolution images at different sizes and aspect ratios and need to resize them down to a uniform size and aspect ratio without squashing and stretching.

Is there an equivalent to this in Tensorflow that can be mapped across a Tensorflow dataset, or a lambda function using tensorflow operations that would achieve the same effective result?

Upvotes: 3

Views: 1422

Answers (2)

Zaccharie Ramzi
Zaccharie Ramzi

Reputation: 2326

I couldn't find any equivalent in the library, but a somewhat "official" solution is present in the NNCLR tutorial. It indeed relies on the tf.image.crop_and_resize function, as @TFer pointed out.

I modified it a bit to make sure it also has the equivalent of the size argument in the PyTorch implementation, that I called crop_shape that I found clearer:

import tensorflow as tf


class RandomResizedCrop(tf.keras.layers.Layer):
    # taken from
    # https://keras.io/examples/vision/nnclr/#random-resized-crops
    def __init__(self, scale, ratio, crop_shape):
        super(RandomResizedCrop, self).__init__()
        self.scale = scale
        self.log_ratio = (tf.math.log(ratio[0]), tf.math.log(ratio[1]))
        self.crop_shape = crop_shape

    def call(self, images):
        batch_size = tf.shape(images)[0]

        random_scales = tf.random.uniform(
            (batch_size,),
            self.scale[0],
            self.scale[1]
        )
        random_ratios = tf.exp(tf.random.uniform(
            (batch_size,),
            self.log_ratio[0],
            self.log_ratio[1]
        ))

        new_heights = tf.clip_by_value(
            tf.sqrt(random_scales / random_ratios),
            0,
            1,
        )
        new_widths = tf.clip_by_value(
            tf.sqrt(random_scales * random_ratios),
            0,
            1,
        )
        height_offsets = tf.random.uniform(
            (batch_size,),
            0,
            1 - new_heights,
        )
        width_offsets = tf.random.uniform(
            (batch_size,),
            0,
            1 - new_widths,
        )

        bounding_boxes = tf.stack(
            [
                height_offsets,
                width_offsets,
                height_offsets + new_heights,
                width_offsets + new_widths,
            ],
            axis=1,
        )
        images = tf.image.crop_and_resize(
            images,
            bounding_boxes,
            tf.range(batch_size),
            self.crop_shape,
        )
        return images

Upvotes: 2

user11530462
user11530462

Reputation:

You can use tf.image.crop_and_resize to crop and resize the image.

Tensorflow provides,

Returns a tensor with crops from the input image at positions defined at the bounding box locations in boxes. The cropped boxes are all resized (with bilinear or nearest neighbor interpolation) to a fixed size = [crop_height, crop_width].

For more details on the library please find here. Thanks

Upvotes: 0

Related Questions