TensorFlow
image processing
batch operations
machine learning
computer vision

TensorFlow image operations for batches

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

TensorFlow image APIs are often demonstrated on single images, but real training pipelines usually work on batches shaped like [batch, height, width, channels]. Many tf.image operations handle batches naturally, while others are easier to apply with dataset mapping or tf.map_fn. The key is to know which functions broadcast over the batch dimension and how to keep shapes consistent.

Understand the Batch Shape

A standard image batch looks like this:

python
1import tensorflow as tf
2
3images = tf.random.uniform(shape=(8, 128, 128, 3), minval=0, maxval=255, dtype=tf.float32)
4print(images.shape)

That means:

  • '8 images in the batch'
  • height 128
  • width 128
  • '3 channels'

Most TensorFlow vision code assumes this layout.

Operations That Work on Batches Directly

Several image ops accept batched input with no extra work. Resizing is a common example.

python
1import tensorflow as tf
2
3images = tf.random.uniform((8, 128, 128, 3))
4resized = tf.image.resize(images, size=(64, 64))
5
6print(resized.shape)

This resizes every image in the batch and returns another batched tensor.

Casting and normalization also work naturally:

python
images = tf.cast(images, tf.float32) / 255.0

These elementwise operations are batch-friendly by default.

Per-Image Random Augmentation

Random augmentations can be trickier because you usually want randomness applied independently to each image, not one shared decision across the whole batch.

Example with tf.image.random_flip_left_right:

python
1import tensorflow as tf
2
3images = tf.random.uniform((8, 128, 128, 3))
4flipped = tf.image.random_flip_left_right(images)
5print(flipped.shape)

This works on batches, but you should still confirm that the random behavior matches your expectations for the TensorFlow version and pipeline structure you are using.

For more explicit control, map the operation across the batch:

python
1flipped = tf.map_fn(
2    tf.image.random_flip_left_right,
3    images
4)

That pattern is useful when the operation is defined most naturally per image.

Batch Processing Inside tf.data

In real training code, image transforms often belong in the dataset pipeline.

python
1import tensorflow as tf
2
3dataset = tf.data.Dataset.from_tensor_slices(images).batch(4)
4
5def preprocess(batch):
6    batch = tf.image.resize(batch, (64, 64))
7    batch = tf.cast(batch, tf.float32) / 255.0
8    return batch
9
10dataset = dataset.map(preprocess, num_parallel_calls=tf.data.AUTOTUNE)
11dataset = dataset.prefetch(tf.data.AUTOTUNE)

This keeps preprocessing close to input loading and avoids baking image logic into the model unnecessarily.

When tf.map_fn Is Useful

Some operations are easiest to express on one image at a time. In those cases, tf.map_fn helps you lift a single-image function to a batch.

python
1import tensorflow as tf
2
3def center_crop_one(image):
4    return tf.image.central_crop(image, central_fraction=0.8)
5
6cropped = tf.map_fn(center_crop_one, images)
7print(cropped.shape)

Use this when the individual operation is clearer than a fully vectorized batch expression.

Keep Shapes and Dtypes Consistent

Batch image pipelines often fail because one step changes shape or dtype in a way the next step does not expect.

Example:

python
images = tf.random.uniform((8, 128, 128, 3), maxval=256, dtype=tf.int32)
images = tf.cast(images, tf.float32)
images = tf.image.resize(images, (224, 224))

This sequence is fine because the cast happens before image operations that expect floating-point data in many workflows.

If a batch contains mixed shapes, you usually need to resize or pad before batching rather than after.

Prefer Keras Preprocessing Layers for Model Pipelines

For common augmentations during training, Keras preprocessing layers can be simpler than hand-writing tf.image calls.

python
1import tensorflow as tf
2
3augment = tf.keras.Sequential([
4    tf.keras.layers.RandomFlip("horizontal"),
5    tf.keras.layers.RandomRotation(0.05),
6    tf.keras.layers.Rescaling(1.0 / 255.0),
7])
8
9output = augment(images)
10print(output.shape)

This is often easier to integrate into modern Keras models than a large set of manual image ops.

Common Pitfalls

The biggest mistake is assuming every tf.image function behaves the same way on batched input. Some are naturally batch-friendly, while others are clearer and safer when mapped per image.

Another issue is losing track of shape and dtype, especially when mixing integer image tensors, resizing, and model normalization.

Developers also sometimes apply augmentation after batching without confirming whether the randomness is per image or shared in the way they expect.

Summary

  • TensorFlow image batches usually have shape [batch, height, width, channels].
  • Many tf.image operations such as resize work directly on batched tensors.
  • Use tf.map_fn when the operation is easiest to express per image.
  • Keep image shape and dtype consistent through the pipeline.
  • Consider Keras preprocessing layers when batch augmentation needs to stay simple and maintainable.

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.