TensorFlow
CNN
image preprocessing
training data
deep learning

Tensorflow CNN training images are all different sizes

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

CNN training data often contains images with different widths and heights, but a standard training batch usually needs a consistent tensor shape. In practice, that means you almost always resize, crop, or pad images before batching them.

TensorFlow gives you several ways to do this cleanly in tf.data. The right choice depends on whether aspect ratio matters, whether you can tolerate distortion, and whether your model can accept variable input shapes during inference.

Why Variable Sizes Are a Problem

A CNN layer can operate on different spatial dimensions in theory, but batched training is stricter. A batch is one tensor, and every element in that tensor must share the same shape.

So while a single image of shape 200 x 300 x 3 and another of shape 480 x 640 x 3 are both valid individually, they cannot be stacked into one dense batch without preprocessing.

Resize Everything to a Fixed Shape

The simplest approach is resizing every image to the same target size.

python
1import tensorflow as tf
2
3TARGET_SIZE = (224, 224)
4
5def load_and_resize(path, label):
6    image = tf.io.read_file(path)
7    image = tf.image.decode_jpeg(image, channels=3)
8    image = tf.image.resize(image, TARGET_SIZE)
9    image = image / 255.0
10    return image, label

This is easy and fast, but it can distort the image if the original aspect ratio is not square.

Preserve Aspect Ratio With Padding

If distortion is a problem, resize while preserving aspect ratio and then pad to the target dimensions.

python
1import tensorflow as tf
2
3TARGET_HEIGHT = 224
4TARGET_WIDTH = 224
5
6def load_resize_with_pad(path, label):
7    image = tf.io.read_file(path)
8    image = tf.image.decode_jpeg(image, channels=3)
9    image = tf.image.resize_with_pad(image, TARGET_HEIGHT, TARGET_WIDTH)
10    image = image / 255.0
11    return image, label

This is a good default for many classification tasks because it avoids stretching objects unnaturally.

Cropping as an Alternative

For some image problems, especially when the subject is usually centered, cropping can work better than padding. You can resize the shorter side and then crop a fixed window.

python
1import tensorflow as tf
2
3def random_crop_example(image):
4    image = tf.image.resize(image, [256, 256])
5    image = tf.image.random_crop(image, size=[224, 224, 3])
6    return image

Cropping is commonly used as part of data augmentation, but it can remove important content if the target object is near the edge.

A Complete tf.data Pipeline

Here is a minimal pipeline that loads variable-size JPEG files and produces normalized fixed-size batches:

python
1import tensorflow as tf
2
3paths = tf.constant(["cat1.jpg", "cat2.jpg", "cat3.jpg"])
4labels = tf.constant([0, 1, 0])
5
6dataset = tf.data.Dataset.from_tensor_slices((paths, labels))
7dataset = dataset.map(load_resize_with_pad, num_parallel_calls=tf.data.AUTOTUNE)
8dataset = dataset.shuffle(100)
9dataset = dataset.batch(32)
10dataset = dataset.prefetch(tf.data.AUTOTUNE)

Once the resize or padding step is in place, batching works normally.

Can the Model Accept Variable Input Shapes?

Some TensorFlow and Keras models can declare None for height and width, especially when they avoid dense layers early in the network.

python
1model = tf.keras.Sequential([
2    tf.keras.layers.Input(shape=(None, None, 3)),
3    tf.keras.layers.Conv2D(16, 3, activation="relu"),
4    tf.keras.layers.GlobalAveragePooling2D(),
5    tf.keras.layers.Dense(2, activation="softmax"),
6])

That helps at inference time for single images, but it does not remove the batching requirement. During training, each batch still needs consistent dimensions unless you use more advanced bucketing or per-example processing strategies.

Common Pitfalls

The most common mistake is decoding images and calling batch() before resizing or padding. TensorFlow then fails because it cannot combine tensors with different shapes.

Another issue is ignoring aspect ratio. A naive resize to a square input can silently reduce model quality if object shape matters.

Be careful with image data types too. Many image ops return floating point tensors, so normalize consistently and make sure the model sees the range it expects.

Finally, remember that pretrained models often expect a specific input size and preprocessing rule. Match those exactly when fine-tuning.

Summary

  • Variable-size images usually need preprocessing before batched CNN training.
  • Resizing to a fixed shape is the simplest approach.
  • 'tf.image.resize_with_pad preserves aspect ratio better than a plain stretch.'
  • Models can support variable image sizes at inference, but batches still need consistent dimensions.
  • Put the resize, crop, or pad step inside the tf.data pipeline before batching.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.