Digital Image Fundamentals
First Steps in Computer Vision
What Is a Digital Image?
A digital image is a collection of pixels (picture elements) arranged in a two-dimensional grid. Each pixel has a position $(x, y)$ and a brightness value (or color value).
Why the y-axis points downward
In mathematical graphs the y-axis is drawn pointing upward. In image processing, however, the origin is placed at the top-left and the y-axis points downward. This convention originates from the CRT display era, when the electron beam performed a raster scan across the screen from left to right and top to bottom. In memory, image data is often stored starting from the top-left pixel, so increasing row numbers correspond to lower positions on the screen. This convention has been inherited by many image formats and image processing libraries (OpenCV, PIL, etc.), but there are exceptions: BMP stores rows from the bottom by default, and OpenGL texture coordinates put the origin at the bottom-left.
Resolution and Bit Depth
Resolution
Here, resolution refers to the number of pixels in an image (its pixel dimensions); in printing and displays, the number of pixels per inch (dpi/ppi) is also called resolution. It is expressed as $W \times H$; for example, 1920×1080 is approximately 2 million pixels. The terms "4K" and "8K" used for TVs and displays derive from the horizontal pixel count: 4K is 3840×2160 (approximately 8.3 million pixels) and 8K is 7680×4320 (approximately 33 million pixels).
Note: Consumer TVs and displays use "4K UHD" (3840×2160), which differs from the cinema industry's "DCI 4K" (4096×2160).
Bit Depth
The number of bits used to represent one channel (one value). The number of bits per pixel is this times the number of channels:
- 1-bit: binary image (black and white)
- 8-bit: 256 levels (0 to 255). For $n$ bits, values range from $0$ to $2^n - 1$
- 16-bit: 65,536 levels
- 24-bit (per pixel): 8 bits for each of the 3 RGB channels (full color)
Number of Channels
Number of Channels
The number of values each pixel holds.
| Channels | Name | Pixel Values | Use Cases |
|---|---|---|---|
| 1 | Grayscale | 1 brightness value | B&W photos, medical imaging, edge detection preprocessing |
| 3 | Color (RGB) | 3 values: red, green, blue | General color images |
| 4 | RGBA | 4 values: red, green, blue, alpha | PNG, icons, UI design |
The more channels a pixel has, the more data it requires. In image processing, a common technique is to convert a color image to grayscale (1 channel) to reduce the computational cost. The specific conversion formula (for example $Y = 0.299R + 0.587G + 0.114B$, with ITU-R BT.601 coefficients applied to gamma-corrected RGB) is covered in “Color Spaces”.
Image Memory Size
The size of an uncompressed pixel array in memory can be calculated as follows (JPEG and PNG files are compressed, so file sizes differ):
$$\text{Size (bytes)} = W \times H \times \frac{\text{bit depth per channel}}{8} \times \text{number of channels}$$Example: 1920×1080 Full HD image
- Grayscale (8-bit): $1920 \times 1080 \times 1 = 2,073,600$ bytes ≈ 2MB
- Color (24-bit RGB): $1920 \times 1080 \times 3 = 6,220,800$ bytes ≈ 6MB
Mathematical Representation of Images
An image can be represented mathematically as follows:
Grayscale Image
Represented as a matrix $\mathbf{I} \in \mathbb{R}^{H \times W}$, whose entry in row $y$ and column $x$ is the brightness value $I(x,y)$ of pixel $(x, y)$.
$$\mathbf{I} = \begin{pmatrix} I(0,0) & I(1,0) & \cdots & I(W-1,0) \\ I(0,1) & I(1,1) & \cdots & I(W-1,1) \\ \vdots & \vdots & \ddots & \vdots \\ I(0,H-1) & I(1,H-1) & \cdots & I(W-1,H-1) \end{pmatrix}$$Note: Viewing the image as a function we write $I(x, y)$ (horizontal, vertical), but as a matrix or array the indices go row then column, so NumPy/OpenCV access pixels as img[y, x].
Color Image
A 3D tensor $\mathbf{I} \in \mathbb{R}^{H \times W \times C}$ (C: number of channels, typically 3)
$$I(x, y) = \begin{pmatrix} R(x,y) \\ G(x,y) \\ B(x,y) \end{pmatrix}$$Why does OpenCV use BGR ordering?
Many image libraries (PIL, matplotlib, etc.) handle color images as arrays in RGB order, but OpenCV's imread returns arrays in BGR order.
This is not due to technical merit but rather historical circumstance.
When Intel began developing OpenCV in 1999, the dominant camera API on Windows (Video for Windows) and the bitmap format (BMP/DIB) returned data in BGR order, and OpenCV is said to have followed suit.
Windows BMP is said to use BGR because a pixel treated as the 32-bit integer 0xAARRGGBB (A, R, G, B from the high byte) is laid out in memory on little-endian Intel x86 as B, G, R, A.
Even after OpenCV became cross-platform, BGR ordering has been retained for backward compatibility with existing code.
When displaying an image loaded with OpenCV in other libraries (PIL, matplotlib, etc.), you need to convert it using cv2.cvtColor(img, cv2.COLOR_BGR2RGB).
Code Example (Python)
import numpy as np
import cv2
# Load an image
img_color = cv2.imread('image.jpg') # Color (H, W, 3)
img_gray = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) # Grayscale (H, W)
# Image properties
print(f"Shape: {img_color.shape}") # (height, width, channels)
print(f"Dtype: {img_color.dtype}") # uint8 (0-255)
print(f"Size: {img_color.nbytes} bytes") # Total bytes (.size is the element count; equal for uint8)
# Accessing a pixel
pixel = img_color[100, 200] # (B, G, R) values
gray_value = img_gray[100, 200] # Brightness value
# Creating new images
blank = np.zeros((480, 640, 3), dtype=np.uint8) # Black image
white = np.ones((480, 640), dtype=np.uint8) * 255 # White image
Summary
- A digital image is a 2D array of pixels
- Resolution defines the number of pixels; the bit depth per channel determines the number of levels of each channel
- Grayscale images are 2D matrices; color images are 3D tensors
- Matrix operations form the foundation of image processing
Frequently Asked Questions
Why does the y-axis point downward in digital images?
This convention dates back to the CRT display era, when the electron beam scanned the screen from left to right and top to bottom in a raster scan. In memory, image data is often stored starting from the top-left pixel, so increasing row numbers correspond to lower positions on the screen. The convention has been carried over to many image processing libraries such as OpenCV and PIL, but there are exceptions: BMP stores rows from the bottom by default, and OpenGL texture coordinates put the origin at the bottom-left.
Why does OpenCV use BGR ordering?
OpenCV was started at Intel in 1999, and it is said to have followed the BGR order used at the time by the Windows camera APIs and the BMP format. BMP's BGR order is said to come from treating a pixel as the 32-bit integer 0xAARRGGBB: laid out in memory on little-endian x86, its bytes appear as B, G, R, A. For backward compatibility, OpenCV still uses BGR today.