TensorFlow
image processing
computer vision
machine learning
Python

Tensorflow image reading display

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

Reading and displaying images correctly is a core step in TensorFlow computer vision pipelines. Small preprocessing mistakes such as wrong dtype, unexpected channel count, or inconsistent normalization can silently hurt model quality. A robust image workflow makes shape, range, and resize behavior explicit in shared code.

Read and Decode Image Files Safely

TensorFlow reads image files as raw bytes first, then decodes bytes into tensors.

python
1import tensorflow as tf
2
3path = "sample.jpg"
4raw = tf.io.read_file(path)
5img = tf.io.decode_jpeg(raw, channels=3)
6
7print("shape:", img.shape)
8print("dtype:", img.dtype)

For JPEG, decoded output is typically uint8 with value range from zero to two hundred fifty five.

Use format-specific decode functions when possible for predictable behavior.

Convert Dtype and Normalize Once

Most models expect floating-point input. Convert and normalize early, then keep that policy consistent.

python
1import tensorflow as tf
2
3img_f32 = tf.image.convert_image_dtype(img, tf.float32)
4print(tf.reduce_min(img_f32).numpy(), tf.reduce_max(img_f32).numpy())

convert_image_dtype scales integer images into zero to one range, which is common for TensorFlow models.

Resize and Add Batch Dimension

Model signatures often require fixed size and batch axis.

python
1import tensorflow as tf
2
3resized = tf.image.resize(img_f32, [224, 224])
4batched = tf.expand_dims(resized, axis=0)
5
6print("resized:", resized.shape)
7print("batched:", batched.shape)

Explicitly checking shapes prevents inference-time errors.

Display TensorFlow Images for Verification

TensorFlow focuses on tensor ops, so use Matplotlib for visual inspection.

python
1import matplotlib.pyplot as plt
2
3plt.figure(figsize=(4, 4))
4plt.imshow(resized.numpy())
5plt.title("Preprocessed Image")
6plt.axis("off")
7plt.show()

Visual validation helps catch channel-order mistakes, cropping errors, and unexpected interpolation artifacts.

Build a Reusable Loader Function

A shared loader function prevents training and inference from drifting apart.

python
1import tensorflow as tf
2
3
4def load_image(path: str, size: tuple[int, int] = (224, 224)) -> tf.Tensor:
5    raw = tf.io.read_file(path)
6    img = tf.io.decode_image(raw, channels=3, expand_animations=False)
7    img = tf.image.convert_image_dtype(img, tf.float32)
8    img = tf.image.resize(img, size)
9    return img
10
11
12x = load_image("sample.jpg")
13print(x.shape, x.dtype)

Reusing one function across notebooks and services improves consistency.

Scale to Datasets With tf.data

For real workloads, build streaming pipelines instead of loading files one by one.

python
1import tensorflow as tf
2
3files = tf.data.Dataset.list_files("images/*.jpg", shuffle=True)
4
5def parse(path: tf.Tensor) -> tf.Tensor:
6    raw = tf.io.read_file(path)
7    img = tf.io.decode_jpeg(raw, channels=3)
8    img = tf.image.convert_image_dtype(img, tf.float32)
9    img = tf.image.resize(img, [224, 224])
10    return img
11
12ds = (
13    files
14    .map(parse, num_parallel_calls=tf.data.AUTOTUNE)
15    .batch(32)
16    .prefetch(tf.data.AUTOTUNE)
17)
18
19for batch in ds.take(1):
20    print(batch.shape)

This improves throughput and keeps GPU pipelines fed.

Handle Corrupt Images and Edge Cases

Production datasets often contain corrupt files or unexpected formats. Add guarded parsing or filtering so one bad file does not stop the entire pipeline.

python
1import tensorflow as tf
2
3
4def safe_parse(path: tf.Tensor):
5    try:
6        raw = tf.io.read_file(path)
7        img = tf.io.decode_image(raw, channels=3, expand_animations=False)
8        img = tf.image.convert_image_dtype(img, tf.float32)
9        img = tf.image.resize(img, [224, 224])
10        return img
11    except Exception:
12        return tf.zeros([224, 224, 3], dtype=tf.float32)

For strict training jobs, logging and dropping invalid samples may be better than zero-filling.

Keep Training and Serving Preprocessing Identical

Many model regressions come from mismatched preprocessing between training and inference. Use shared preprocessing code or add parity tests.

python
1import numpy as np
2
3train_tensor = load_image("sample.jpg")
4serve_tensor = load_image("sample.jpg")
5
6np.testing.assert_allclose(train_tensor.numpy(), serve_tensor.numpy(), rtol=1e-5, atol=1e-6)

A simple parity test can prevent hard-to-debug deployment drift.

Common Pitfalls

A common pitfall is feeding raw uint8 images to models trained on normalized floats. Another is forgetting batch dimension before inference. Teams often mix RGB assumptions with BGR pipelines from other libraries. Inconsistent resize settings between training and serving are also frequent. Finally, image pipelines are often shipped without checks for corrupt files and value ranges.

Summary

  • Read images as bytes, then decode explicitly by format.
  • Convert dtype and normalization consistently across all code paths.
  • Resize and batch tensors to match model signatures.
  • Use Matplotlib for visual preprocessing validation.
  • Use tf.data for scalable image loading pipelines.
  • Enforce training-serving preprocessing parity with shared code and tests.

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.