Skip to main content

Images as Tensors

An image file is encoded bytes; a model receives a numeric tensor. The conversion contract must name the axis order, dtype, value range, color space, and normalization. This path uses (N, C, H, W): batch, channel, height, width.

Prerequisites​

Complete Tensors, Gradients, and Autodiff. You should recognize shapes, dtypes, and broadcasting.

Learning goals​

  • distinguish file layout (H, W, C) from PyTorch's common (C, H, W) layout.
  • scale uint8 values in [0, 255] to floating-point values in [0, 1] deliberately.
  • apply per-channel normalization without mixing batch or spatial axes.

Worked example​

This generated 2-by-3 RGB image has a visible, auditable value in every channel. permute changes axis order; it does not change the pixels. The leading dimension is then added for a one-image batch.

import torch

image_hwc = torch.tensor(
[
[[255, 0, 0], [0, 255, 0], [0, 0, 255]],
[[255, 255, 255], [0, 0, 0], [128, 64, 32]],
],
dtype=torch.uint8,
)
image_chw = image_hwc.permute(2, 0, 1).to(torch.float32) / 255.0
batch = image_chw.unsqueeze(0)
mean = torch.tensor([0.5, 0.5, 0.5])[:, None, None]
normalized = (image_chw - mean) / mean

print(f"file_like={tuple(image_hwc.shape)} dtype={image_hwc.dtype} range=({image_hwc.min()}, {image_hwc.max()})")
print(f"model_batch={tuple(batch.shape)} dtype={batch.dtype} range=({batch.min():.1f}, {batch.max():.1f})")
print(f"normalized_pixel={[round(v, 1) for v in normalized[:, 0, 0].tolist()]}")

Output:

file_like=(2, 3, 3) dtype=torch.uint8 range=(0, 255)
model_batch=(1, 3, 2, 3) dtype=torch.float32 range=(0.0, 1.0)
normalized_pixel=[1.0, -1.0, -1.0]

Real decoders must also define color conversion: grayscale, RGB, RGBA, and CMYK are not interchangeable. When resizing, specify the output (height, width), interpolation, and antialiasing. Bilinear interpolation is sensible for continuous-color images; nearest-neighbor interpolation is normally required for integer class masks so interpolation does not invent label IDs.

Common mistakes​

  • Treating (H, W, C) as (C, H, W) because both contain three dimensions.
  • Dividing values already in [0, 1] by 255 again, or feeding uint8 to a floating-point model.
  • Copying normalization constants from pretrained weights without using the matching color order and preprocessing recipe.
  • Computing dataset mean and standard deviation before the split, which leaks validation and test pixels.
  • Resizing an image without documenting aspect-ratio distortion or interpolation.

Practice​

Change the pixel at row 1, column 2 to [255, 128, 0]. Predict its three normalized values before running. Then explain which axes a batch of four 64-by-96 RGB images would have.

Next steps​

Continue with Convolution and Pooling to exploit spatial locality while preserving the tensor contract.

Primary sources​

Checked 2026-10-16: TorchVision tensor image conventions, TorchVision ToDtype, TorchVision Normalize, and TorchVision Resize.