TensorFlow
image processing
image distortion
machine learning
Python

TensorFlow How to apply the same image distortion to multiple images

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When you need to apply the same image distortion to multiple images, the key idea is to share the random parameters rather than calling independent random augmentation functions on each image. This matters for tasks such as segmentation, paired image translation, stereo input, or multi-view learning, where the images must stay aligned after augmentation.

Why Independent Random Calls Fail

If you call a random augmentation separately for each image, each image gets its own random flip, crop, rotation, or brightness change.

python
augmented_a = tf.image.random_flip_left_right(image_a)
augmented_b = tf.image.random_flip_left_right(image_b)

That is fine for unrelated samples, but it is wrong for paired inputs such as an image and its mask. The two results may no longer correspond spatially.

Use Shared Random Parameters

A simple pattern is to sample the random decision once and apply it to both images.

python
1import tensorflow as tf
2
3
4def same_horizontal_flip(image_a, image_b):
5    do_flip = tf.random.uniform(()) > 0.5
6    if do_flip:
7        image_a = tf.image.flip_left_right(image_a)
8        image_b = tf.image.flip_left_right(image_b)
9    return image_a, image_b

This works because the randomness is generated once, not per image.

Prefer Stateless Random Ops for Determinism

TensorFlow also provides stateless random image functions. With a shared seed, the same random transformation is applied reproducibly.

python
1import tensorflow as tf
2
3
4def same_stateless_flip(image_a, image_b, seed):
5    image_a = tf.image.stateless_random_flip_left_right(image_a, seed=seed)
6    image_b = tf.image.stateless_random_flip_left_right(image_b, seed=seed)
7    return image_a, image_b
8
9
10seed = tf.constant([123, 456], dtype=tf.int32)
11image_a, image_b = same_stateless_flip(image_a, image_b, seed)

This is usually the best choice in data pipelines because it makes the transformation reproducible and explicit.

Apply Shared Geometric Parameters

For transformations that are not provided as a single shared random op, sample the parameters yourself and reuse them.

python
1import tensorflow as tf
2
3
4def same_rot90(image_a, image_b):
5    k = tf.random.uniform((), minval=0, maxval=4, dtype=tf.int32)
6    return tf.image.rot90(image_a, k), tf.image.rot90(image_b, k)

The same idea applies to cropping. Compute one crop window and apply it to every aligned image.

python
1import tensorflow as tf
2
3
4def same_crop(image_a, image_b, crop_height, crop_width):
5    shape = tf.shape(image_a)
6    offset_y = tf.random.uniform((), 0, shape[0] - crop_height + 1, dtype=tf.int32)
7    offset_x = tf.random.uniform((), 0, shape[1] - crop_width + 1, dtype=tf.int32)
8
9    image_a = tf.image.crop_to_bounding_box(image_a, offset_y, offset_x, crop_height, crop_width)
10    image_b = tf.image.crop_to_bounding_box(image_b, offset_y, offset_x, crop_height, crop_width)
11    return image_a, image_b

Pair Augmentations Inside tf.data

In a tf.data pipeline, keep paired images together and augment them in one mapping function.

python
1import tensorflow as tf
2
3
4def augment_pair(image, mask):
5    seed = tf.constant([7, 21], dtype=tf.int32)
6    image = tf.image.stateless_random_flip_left_right(image, seed)
7    mask = tf.image.stateless_random_flip_left_right(mask, seed)
8    return image, mask
9
10
11dataset = dataset.map(augment_pair, num_parallel_calls=tf.data.AUTOTUNE)

This preserves alignment because the transformation is sampled once per pair and applied consistently inside one dataset element. It also keeps augmentation logic easier to test.

Common Pitfalls

  • Calling random augmentation separately on each aligned image and breaking correspondence.
  • Using ordinary random functions when deterministic shared seeds would make debugging easier.
  • Sampling shared parameters from one image shape and applying them to another image with different dimensions.
  • Applying geometric transforms consistently but forgetting that some label masks need different interpolation rules than RGB images.
  • Splitting paired images into separate dataset pipelines before augmentation.

Summary

  • To apply the same distortion to multiple images, share the random parameters.
  • Stateless random image ops are a strong default when TensorFlow provides them.
  • For other transforms, sample the parameters yourself and reuse them.
  • Keep paired images together in the same tf.data mapping function.
  • Alignment-sensitive tasks fail if each image gets its own independent random augmentation.

Course illustration
Course illustration

All Rights Reserved.