Skip to course content
Free computer vision course

Computer Vision and Multimodal AI

Unit 01.00: An image is a grid of numbers

Everything in computer vision follows from one fact: an image is a grid of numbers, and nothing in it knows what it depicts.

Height, then width, then channels

A colour image is a three-dimensional array. The first axis is rows, the second is columns, the third is colour channels.

The code builds a tiny image and prints its parts.

import numpy as np

image = np.zeros((4, 6, 3), dtype="uint8")
image[1:3, 2:5] = [40, 180, 220]

print("shape:", image.shape, "-> (height, width, channels)")
print("dtype:", image.dtype, "-> values 0-255")
print("\nthe blue channel, as numbers:")
print(image[:, :, 2])

print(f"\none pixel: {image[1, 2]}  (a 3-value array, not a colour)")
print(f"mean brightness: {image.mean():.1f}")

# Height comes first, then width. Every off-by-one in a vision pipeline starts
# here: numpy indexes rows before columns, and almost every drawing API takes
# x before y.

Height comes first. Almost every drawing API takes x before y, and numpy indexes rows before columns, so the two conventions are transposed with respect to each other.

That is where a large share of off-by-one and transposed-image bugs originate. A pixel is image[y, x] and a point is usually (x, y), and both are correct in their own context.

The mistake this prevents

The mistake is reasoning about images as pictures rather than arrays. A picture has a left and a top; an array has axis 0 and axis 1, and which one is vertical is a convention you have to keep track of deliberately.

Takeaway

An image is a (height, width, channels) array of numbers. Rows before columns in numpy, x before y almost everywhere else.