Modules / Computer Vision / RGB Processing

RGB Image Logic

Draw with colors to understand how images are composed of Red, Green, and Blue channels.

Pixel Matrix Breakdown

LIVE CHANNELS

Overview

Draw with colors to understand how images are composed of Red, Green, and Blue channels.

In this guide
  1. Start here
  2. The Core Idea: Channels as Layers
  3. Three counts per pixel
  4. Other colour spaces, and why they exist
  5. Feeding colour pics to a network
  6. Guided Experiments with This Interactive
  7. Thinking in Pseudocode
  8. Common Mistakes & Pitfalls
  9. What the three channels really hold
  10. Summing up
  11. When colour carries the answer, and when it misleads
  12. Common mistakes
  13. Questions people ask
  14. Recap in one screen

Understanding RGB Image Processing

A deep explore how digital color is represented and manipulated. Read this, experiment with the tool, and solidify your understanding.

Start here

RGB Pic Handling is a basic concept in computer vision. It's the basis for how computers "see" and manipulate color pics. Each colored pixel on your screen is a combination of three vals: Red, Green, and Blue.

Each value ranges from 0 (none of that colour) to 255 (max intensity). Mixing the three channels additively gives each colour the display can show: (255, 0, 0) is pure red, (0, 255, 0) is pure green, (255, 255, 0) is yellow, (255, 255, 255) is white and (0, 0, 0) is black. The total count of representable colours is 256³ — roughly 16.7 million.

In code, an pic is a 3D NumPy array of shape (height, width, 3). The first two axes are pixel coordinates (rows from top, columns from left). The third axis is the channel index: 0 for red, 1 for green, 2 for blue. Extracting a single channel (pic[:, :, 0]) gives a 2D grayscale array showing how much red each pixel holds.

OpenCV reads pics in BGR order rather than RGB — a historical accident. Forgetting to turn with cv2.cvtColor(img, cv2.COLOR_BGR2RGB) swaps the red and blue channels, giving pics that look wrong in ways that are obvious on faces (blue skin) but easy to miss on other subjects.

Other colour spaces — HSV, LAB, YCbCr — rearrange the same information for other tasks. HSV separates hue from brightness, making it easy to select all pixels of a particular colour no matter lighting. LAB nets perceptual distance. So numerically close colours look close to the human eye. All are computed from the underlying RGB vals.

The Core Idea: Channels as Layers

Think of a color pic not as a single flat picture. But as three split grayscale pics stacked on top of each other. Each of these "layers" is a channel, showing the intensity of Red, Green. Or Blue light for each pixel.

  • The Red Channel shows where the pic is most red.
  • The Green Channel shows where it's most green.
  • The Blue Channel shows where it's most blue.

When mixed, their vals mix to create the full spectrum of colors we see. A value of (0, 0, 0) is black, (255, 255, 255) is white. And (255, 0, 0) is pure red.

In code, an RGB pic is a 3D NumPy array of shape (height, width, 3). The first axis is rows (top to bottom), the second is columns (left to right). And the third is the channel: index 0 for red, 1 for green, 2 for blue. Each value is often a uint8 integer from 0 to 255, giving 256 intensity levels per channel and 256³ ≈ 16.7 million possible colours per pixel.

Extracting a single channel is a slice: pic[:, :, 0] gives the red channel as a 2D grayscale array. Setting a channel to zero removes that colour fully: pic[:, :, 2] = 0 removes all blue. These steps are the foundation of colour manipulation: adjusting brightness means scaling all channels, adjusting contrast means stretching the range of vals. And turning to grayscale means replacing the three channels with a single weighted average (often 0.299R + 0.587G + 0.114B, the luminance formula that matches human perception).

OpenCV reads pics in BGR order rather than RGB. It is a historical accident from early camera hardware. Turning between the two is cv2.cvtColor(pic, cv2.COLOR_BGR2RGB). Forgetting this change is one of the most common bugs in computer vision code — the pic displays with swapped red and blue channels. It is obvious on faces (blue skin) but easy to miss on landscapes.

Other colour spaces — HSV (hue, saturation, value), LAB, YCbCr — rearrange the same information for other purposes. HSV separates colour (hue) from intensity (value), making it easier to select "all red pixels" no matter brightness. LAB is designed so that equal numerical distances correspond to equal perceived colour gaps. It makes it useful for colour comparison. All are computed from RGB.

Three counts per pixel

A colour pic stores three vals per pixel — red, green and blue — each often 0 to 255. Mixing them additively gives each colour the display can show.

RGBColour
25500Red
02550Green
2552550Yellow
255255255White
000Black
128128128Mid grey

Equal vals give a shade of grey. Unequal vals give a hue. That simple fact is the basis of a few quick pic checks.

A 1920×1080 photograph is therefore 1920 × 1080 × 3 = 6.2 million vals, about 6MB uncompressed. In code it is an array of shape (height, width, 3) — and note the order: height first, then width. It is the opposite of how pic sizes are often quoted.

Two conventions cause endless confusion. OpenCV stores pics as BGR, while almost all else uses RGB. So an pic loaded with cv2.imread and displayed with matplotlib comes out with red and blue swapped. And PyTorch expects channels-first tensors, (3, H, W), while NumPy and PIL use channels-last, (H, W, 3).

Other colour spaces, and why they exist

RGB is how displays work, not how colour is best reasoned about. Separating colour from brightness is often far more useful.

HSV — hue (which colour, 0–360°), saturation (how vivid), value (how bright). Selecting "all the red pixels" in RGB means writing rules across three interacting channels. In HSV it is a range on one. This is why HSV is the standard choice for colour-based thresholding. And why colour-jitter augmentation is built in it.

LAB — lightness plus two colour axes, designed so that equal numeric distances correspond to roughly equal perceived gaps. Used for colour matching. And its L channel is what CLAHE is often applied to for contrast enhancement without shifting hues.

YCbCr — brightness plus two chroma channels. JPEG and video compression store chroma at less resolution than luma, since human vision is far more sensitive to brightness detail than to colour detail. That asymmetry is a large part of why pics compress as well as they do.

import cv2
img  = cv2.imread("photo.jpg")                  # BGR
rgb  = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
hsv  = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, (0, 120, 70), (10, 255, 255))   # reds

Feeding colour pics to a network

Three preprocessing steps, in this order.

Turn to the net's expected channel order. RGB for torchvision. And channels-first for the tensor.

Scale to 0–1 by dividing by 255.

Standardise per channel with the pretraining dataset's statistics — for ImageNet, mean [0.485, 0.456, 0.406] and standard deviation [0.229, 0.224, 0.225]. These are per channel since the channels genuinely have other distributions. Natural pics have more energy in red and green than in blue.

Skipping the standardisation is a silent error: the net trains and works, a few points below where it should be, with nothing to show why.

Guided Experiments with This Interactive

Use the tool above to build a strong mental net. Follow these steps:

  1. Draw a Pure Color:
    • Set the brush to pure red (#FF0000). Draw a line.
    • Now, switch the "Pixel Matrix Breakdown" to the Red Channel. You'll see high vals (like 255).
    • Switch to the Green and Blue channels. They will show vals of 0. This proves the color is purely red.
  2. Create a Mixed Color:
    • Clear the canvas. Select a yellow color (#FFFF00). Draw something.
    • Check the channels. The Red and Green channels will have high vals, while the Blue channel will be 0. This is since yellow is an equal mix of red and green light.
  3. Understand Grayscale Change:
    • Draw a colorful pic. Then, click the "Turn Grayscale" button.
    • Notice how the pic loses its color. Now, inspect the channels. The Red, Green, and Blue channels are now identical! A grayscale pic is simply an RGB pic where R=G=B for each pixel.
  4. Explore Inversion:
    • Draw a green (#00FF00) shape. Click "Invert Colors". The shape turns magenta.
    • Why? The first pixel was (R:0, G:255, B:0). The inverted pixel is (R:255-0, G:255-255, B:255-0). It results in (R:255, G:0, B:255) — the color magenta.

Thinking in Pseudocode

When a computer applies a filter, it iterates through each pixel and applies a mathematical rule. For a brightness adjustment, it looks like this:

function adjust_brightness(image, factor):
  for each pixel (x, y) in image:
    original_color = image.get_pixel(x, y) // e.g., (R:50, G:100, B:200)
    
    new_R = original_color.R * factor
    new_G = original_color.G * factor
    new_B = original_color.B * factor
    
    // Clamp values to stay within the 0-255 range
    new_R = min(255, new_R)
    new_G = min(255, new_G)
    new_B = min(255, new_B)
    
    image.set_pixel(x, y, (new_R, new_G, new_B))
  
  return image

This is just what happens when you use the "Brightness" slider and click "Apply".

Common Mistakes & Pitfalls

  • Confusing Additive vs. Subtractive Color: Digital color is additive (mixing light). Adding R, G, and B makes white. This is the opposite of mixing paint (subtractive color), where mixing colors makes black.
  • Ignoring Data Types: Pixel vals are almost always stored as 8-bit unsigned integers (0-255). If an step results in a value like 300 or -50, it must be "clamped" to 255 or 0, respectively. Forgetting this leads to visual artifacts.
  • Thinking Filters "See" Objects: A blur or brightness filter doesn't know it's looking at a car or a face. It's just a simple mathematical rule applied to a grid of counts. The "intelligence" of computer vision comes from more complex nets that learn patterns from these counts.

What the three channels really hold

An RGB pic is three greyscale pics stacked. And almost each colour step is a question about how they relate. This works through channel arithmetic, the gap between per-channel and joint steps. And the two mistakes that cause most colour bugs.

example_01.pyNumPy
Output

The next block continues with the left demonstrations.

example_02.pyNumPy
Output

The next block continues with the left demonstrations.

example_03.pyNumPy
Output

The next block continues with the left demonstrations.

example_04.pyNumPy
Output

The next block continues with the left demonstrations.

example_05.pyNumPy
Output

The next block continues with the left demonstrations.

example_06.pyNumPy
Output

Summing up

  • A color pic is a 3D array of counts: (Height x Width x 3).
  • The three layers are the Red, Green, and Blue channels.
  • Pic handling steps are just mathematical functions applied to the numerical vals of pixels.
  • By isolating and observing the channels, you can understand just how any color or filter works.

When colour carries the answer, and when it misleads

Colour is key when the task depends on it — ripeness, traffic signals, quality control on painted parts, medical staining, species identification. Discarding it there throws away the signal.

But colour is also the most common shortcut a net will latch onto. If each photograph of one class in your dataset was taken in a particular lighting. Or each pic of a defect happens to come from a camera with a other white balance, the net will learn the colour cast rather than the object. It will score well on your test split and fail at once on new data.

Three defences:

  • Colour augmentation — jitter brightness, contrast, saturation and hue in training so the net cannot rely on exact vals.
  • Check with Grad-CAM whether the net is attending to the object or to the background.
  • Test on data from a other source — a other camera, a other day, a other site.

The tied failure is white balance: the same object photographed under daylight and under tungsten lighting has genuinely other RGB vals. Histogram equalisation on the L channel of LAB. Or a grey-world white-balance correction, normalises much of this away.

Common mistakes

  • BGR/RGB confusion, which makes pics look wrong and nets underperform for no visible reason.
  • Forgetting the channel order for tensors — a (H, W, 3) array passed where (3, H, W) is expected either errors or silently transposes the pic.
  • Skipping normalisation with a pretrained net.
  • Averaging channels for greyscale instead of with the perceptual weighting.
  • Assuming 8 bits. Medical and scientific pics are often 16-bit. And dividing them by 255 gives vals in the thousands.
  • Applying colour augmentation to a colour-dependent task, destroying the very signal the net needs.

Questions people ask

Why does my pic look blue-tinted? BGR loaded as RGB. Turn with cv2.cvtColor.

Should I turn to greyscale? Just if colour genuinely carries no information for the task. Test both — it is cheap to check.

What is alpha? A fourth channel for transparency, giving RGBA. Most nets expect three channels, so composite onto a background first.

Which colour space for thresholding? HSV, almost always — hue is one axis there and three interacting ones in RGB.

Do CNNs learn colour features? Yes — the first layer of trained networks holds colour-opponent filters alongside the edge detectors.

Why per-channel normalisation rather than one global mean? Since the three channels have genuinely other distributions in natural pics. And treating them identically leaves a systematic offset.

Recap in one screen

  • An RGB pic is three grids of intensities. Equal vals are grey, unequal vals are a hue.
  • OpenCV uses BGR and PyTorch uses channels-first — two conventions that cause most pic-loading bugs.
  • HSV separates colour from brightness and is the right space for colour thresholding and jitter.
  • Scale to 0–1 and standardise per channel with the pretrained net's statistics.
  • Colour is often the signal. And just as often the shortcut a net will exploit — augment and verify.

Recall check

0 of 3

Say the answer out loud before you reveal it — recalling it is what makes it stick, and rereading it is not.

  1. What does this module say about “Start here”?

  2. What does this module say about “The Core Idea: Channels as Layers”?

  3. What does this module say about “Three counts per pixel”?

Cheat sheet

RGB Image Processing

Split a colour image into red, green and blue channels and see how three grids of numbers combine into every pixel.

COMPUTER VISION · vizlearn.in/computer_vision/rgb_image_processing.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.