JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

Color: How a Pixel Holds a Hue

Upgrade the single brightness number into three, and watch how mixing red, green and blue light lets one tiny pixel paint any color you can see.

Three Numbers Make a Color

In the previous guide we agreed on a simple idea: a grayscale pixel is just one number, a single measure of brightness running from black (0) to white (255). That one number is honest, but it is colour-blind. It can tell you how bright a spot is, yet it can never tell you whether you are looking at a red apple or a green leaf of exactly the same brightness. To let a pixel carry colour, we do something almost embarrassingly simple: instead of storing one number, we store three. Those three numbers are the amounts of red, green and blue light at that spot, and together they make up the RGB colour model.

Here is the single most important picture to hold in your head: this is mixing light, not paint. Imagine three flashlights in a dark room — one red, one green, one blue — all shining onto the same white wall. Each number (R, G, B) is a dimmer switch for one flashlight, going from 0 (off) up to 255 (fully on). When light beams overlap, they add together and get brighter. So three flashlights at full power do not give you a muddy dark blob — they give you a bright white patch where all three overlap. Turning every dimmer to zero leaves the wall pitch black. More light means brighter; this is called additive colour mixing.

One colour pixel is three brightness numbers (R, G, B); each controls how much of one coloured light is present.

A colour image shown alongside its three separate red, green and blue channels, each rendered as a grayscale layer.

Let us nail it down with concrete triples, written as (R, G, B). Pure red is (255, 0, 0): red flashlight full on, the other two off. Pure green is (0, 255, 0); the wall glows green. Turn everything off and you get (0, 0, 0) = black. Turn everything fully on and the three lights pile up into (255, 255, 255) = white. The fun one is yellow: there is no yellow flashlight, yet (255, 255, 0) — full red plus full green, no blue — looks yellow to your eye. Your eye reads 'lots of red light and lots of green light arriving together' as the single sensation 'yellow'. That is the whole trick: three dials, and every colour you can see is some setting of those dials.

# A colour pixel is just a triple of three 8-bit numbers (0..255).
# Same idea as the single grayscale number from guide 1 -- now there are three.
red    = (255,   0,   0)   # full red light, nothing else
green  = (  0, 255,   0)   # full green light
white  = (255, 255, 255)   # all three lights full on -> ADD up to white
black  = (  0,   0,   0)   # all lights off
yellow = (255, 255,   0)   # red + green light, no blue -> looks yellow

# Brightness ADDS: more light per channel = brighter, never darker.
# (This is the opposite of mixing paint, which gets darker.)
Five colours as RGB triples. Notice white is 'everything on', the reverse of the paint intuition.

Channels: Stacking Three Grayscale Images

So far we have looked at one pixel. Now zoom out to a whole picture. In guide 1 a grayscale digital image was a 2-D grid of numbers with shape H×W (H rows tall, W columns wide), one brightness value per cell. A colour image is the same grid, but now every cell holds three numbers instead of one. We can picture that as three full grids stacked on top of each other: one grid holding all the red values, one holding all the green values, one holding all the blue. Each of these grids is called a channel. The whole thing has shape H×W×3 — height, width, and a depth of 3 for the three colours.

Here is the connection that ties everything back to guide 1: each single channel is itself just a grayscale image. The red channel, looked at on its own, is a 2-D grid of one-number-per-pixel values, exactly the kind of grayscale array you already understand — except now each number means 'how much red light is here' rather than 'how bright is here'. Same with green and blue. So a colour image is not a new mysterious object; it is three of the old, familiar grayscale images, stacked and re-coloured. Everything you learned about a single grid — rows, columns, 0-to-255 values — applies to each channel unchanged.

Make it visual with a portrait photo of a face. Pull out the red channel alone and display it as grayscale: skin reflects a lot of red light, so cheeks and lips look bright (high values, near white), while a blue shirt looks dark. Now pull out the blue channel: skin reflects relatively little blue, so the same face looks darker and slightly washed-out, while that blue shirt now glows bright. The green channel of a face usually looks the crispest and most detailed, because faces send back plenty of green light. Three different grayscale 'X-rays' of the same scene — and only when you stack them and let your eye add the lights back together do you see a normal colour face.

import numpy as np

# A tiny 2x2 colour image: shape (H=2, W=2, 3).
# Each pixel is [R, G, B].
img = np.array([
    [[255, 0, 0], [0, 255, 0]],   # row 0: red pixel, green pixel
    [[0, 0, 255], [255, 255, 0]], # row 1: blue pixel, yellow pixel
], dtype=np.uint8)

print(img.shape)        # (2, 2, 3)  -> height, width, 3 channels

# Slice out one channel -> it is a plain HxW grayscale grid.
red_channel   = img[:, :, 0]   # just the R numbers
blue_channel  = img[:, :, 2]   # just the B numbers
print(red_channel.shape)       # (2, 2)  -> back to a guide-1 grayscale image
Indexing the third axis pulls out one channel, which is exactly a grayscale H×W array.
A colour image splits into red, green and blue channels — each one a grayscale layer of how much of that colour is present.

An H×W×3 colour image exploded into a stack of three H×W grayscale grids labelled R, G and B.

Bit Depth in Color: Millions of Colors

Guide 1 introduced bit depth: the number of bits used per value decides how many distinct levels that value can take, through L = 2^b. With b = 8 bits, a single grayscale pixel had L = 256 possible brightness levels (0 to 255). Colour reuses that exact idea, three times over. In standard colour we give each channel 8 bits, so each of R, G and B is an independent dial with 256 settings. Three channels × 8 bits = 24 bits per pixel, which is why ordinary colour is called 24-bit colour (or '8 bits per channel'). Nothing new has been invented — we just took the guide-1 dial and bolted on two more.

How many colours does that give? Because the three dials move independently — any red setting can pair with any green and any blue — we multiply the choices together.

\text{Total distinct colours} = (2^{b})^{3} = 2^{3b}

Levels per channel, cubed, because the three channels vary independently.

Let us read this symbol by symbol. b is the bits per channel (the same b from guide 1's L = 2^b). So 2^b is the number of levels one channel can take — for b = 8 that is 2^8 = 256, our familiar 0-to-255 range. We then cube it, the little 3, because there are three independent channels: for every one of the 256 red levels you may freely pick any of 256 greens, and for each of those any of 256 blues. Multiplying independent choices is just 256 × 256 × 256, which is the same as (2^8)^3 = 2^24. Punch it in: 256 × 256 × 256 = 16,777,216 — about 16.7 million distinct colours from one tiny pixel. That is why screens advertise 'millions of colours'; the number falls straight out of three 256-level dials.

Color Spaces: RGB Is Just One Map of Color

We have been treating (R, G, B) as if it were THE definition of colour. It is not — it is just one convenient coordinate system. Think of all the colours a human can perceive as a territory, like a country. RGB is one map of that territory, drawn with three axes (red, green, blue). But the same territory can be described by other maps with different axes, and each is a colour space. Just as a city has both 'street address' and 'latitude/longitude' — two coordinate systems pointing at the very same place — a single colour has an RGB description and other descriptions too. None is more 'real'; you pick the map that makes your current job easiest.

The most useful alternative for beginners is HSV, which re-describes a colour with three more human-friendly axes. Hue is 'which colour' — where you are around the rainbow ring (red, orange, yellow, green, … back to red), usually as an angle from 0° to 360°. Saturation is 'how vivid' — 0 is a washed-out grey, high is a pure punchy colour. Value is 'how bright' — from dark to fully lit. Notice this is exactly how a person describes paint at a hardware store ('a deep, vivid blue, fairly dark'), which is why HSV is so intuitive. The same physical pixel can be written either as (R, G, B) or as (H, S, V); converting between the maps loses nothing.

Why would computer vision bother switching maps? Because HSV pulls apart things that RGB tangles together. In RGB, if a cloud drifts over the sun and the scene dims, all three of R, G and B drop at once — the colour's identity is smeared across all three numbers, so 'what colour is this' and 'how bright is it' are mixed. In HSV, 'what colour' lives almost entirely in Hue while 'how bright' lives in Value. So if you want to find every red object regardless of lighting, you can test 'is the Hue near red?' and largely ignore brightness changes. Separating colour from lighting is one of the most common reasons CV reaches for a different colour space.

There is one especially important map change that goes the other way — from three numbers down to one: converting colour to grayscale. This is a projection, like flattening a 3-D point onto a single line: we collapse (R, G, B) into one brightness number Y. The naive guess is to average them, (R+G+B)/3, but that is wrong for how we actually see. Our eyes are not equally sensitive to the three lights, so the honest conversion is a weighted sum:

Y = 0.299\,R + 0.587\,G + 0.114\,B

Perceptual luminance: a weighted average of the three channels, not a plain mean.

Symbol by symbol: Y is the single output grayscale brightness for the pixel. R, G, B are that pixel's three channel values (the same 0-to-255 numbers from before). The three numbers 0.299, 0.587, 0.114 are weights — how strongly the human eye perceives each colour's contribution to brightness. Green's weight (0.587) is biggest because our eyes are most sensitive to green light, so green contributes the most to how bright something looks; red is middling (0.299) and blue counts for very little (0.114) because our eyes are least sensitive to blue. Crucially the weights sum to 1 (0.299 + 0.587 + 0.114 = 1.000): that makes this a weighted average, not a plain mean, and it guarantees white stays white — feed in (255, 255, 255) and you get 0.299·255 + 0.587·255 + 0.114·255 = 255, still full white. Try a pure green pixel (0, 255, 0): Y = 0.587·255 ≈ 150, a fairly bright grey, while pure blue (0, 0, 255) gives Y = 0.114·255 ≈ 29, almost black — exactly matching the fact that green looks far brighter to us than blue of the same intensity.

Why Computer Vision Cares About Color Representation

Step back and notice the bigger lesson: how you represent colour is an engineering decision, not a fact handed down from nature. The same scene can be a 3-channel digital image, a 1-channel grayscale image, or an HSV array, and a good CV engineer chooses the representation that makes the task easier, faster, or more reliable. The rest of this guide's payoff is learning to ask 'which representation does this job actually need?'

Reason one: size. A colour image carries three numbers per pixel; a grayscale image carries one. So if colour is irrelevant to the task, converting to grayscale immediately cuts the data — and the work — by a factor of 3. A classic example is edge detection, where we only care about where brightness changes sharply (the outline of a door, the edge of a road). Hue does not help there, so most edge detectors run on a single grayscale channel and are 3× lighter for it.

Reason two: robustness to lighting. Picking the right colour space can make an algorithm shrug off changing illumination. Suppose you want to detect skin tones in a video for a face filter. In RGB, skin pixels scatter wildly as the person walks from sunlight into shadow, because all three channels drop together. Convert to HSV (or to a space called Lab) and skin tends to cluster in a tight band of Hue that barely moves when only the brightness changes — so a Hue-based test keeps finding the skin through shadows that would fool an RGB test. Same pixels, smarter map.

Reason three: channels can be processed separately. Because each channel is its own grayscale grid, you are free to treat them independently — boost only the red channel to warm up a photo, denoise the noisy blue channel on its own, or feed all three channels as separate inputs to a later algorithm. The 'stack of grayscale layers' picture from earlier is not just a nice metaphor; it is literally how the data sits in memory, and that layout is what makes per-channel tricks possible.

Hold onto the big picture as we move on. Whether colour or grayscale, HSV or RGB, an image is ultimately a grid of numbers — and that is the door into the rest of computer vision. The next guide asks where that clean grid even comes from, turning smooth real-world light into discrete pixels through sampling and quantization. After that we follow the light backward through a camera, first with the pinhole model and then with the matrices that map the 3-D world onto our 2-D number-grid. Every one of those steps takes the pixels you now understand and pushes them through geometry and, later, learning.