Color Spaces

What are Color Spaces?

A color space is a mathematical model for representing colors as numbers.

Why multiple color spaces?

  • Different tasks need different representations
  • Some spaces better for color segmentation (HSV)
  • Some better for perceptual uniformity (LAB)
  • Some better for storage/transmission (RGB/BGR)

Common color spaces:

  • RGB/BGR: Red, Green, Blue (device-dependent)
  • HSV: Hue, Saturation, Value (perceptually intuitive)
  • LAB: Lightness, A (green-red), B (blue-yellow) (perceptually uniform)

RGB vs BGR

RGB: Red, Green, Blue (standard in most libraries)
BGR: Blue, Green, Red (OpenCV's default)

Why OpenCV uses BGR?

  • Historical reasons (early camera manufacturers)
  • Legacy from older image processing libraries

Important: Always convert BGR to RGB for display with matplotlib!

HSV Color Space

HSV = Hue, Saturation, Value

  • Hue: Color type (0-179 in OpenCV, represents 0-360°)
    • Red: 0°, Green: 120°, Blue: 240°
  • Saturation: Color intensity (0-255)
    • 0 = grayscale, 255 = pure color
  • Value: Brightness (0-255)
    • 0 = black, 255 = brightest

When to use: Color-based object detection, skin detection, color segmentation

BGR to RGB Conversion

  1. import cv2
  2. # opencv uses BGR by default
  3. img_bgr = cv2.imread('image.jpg')
  4. #ans: blue, green, red order
  5. # convert to RGB
  6. img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
  7. #ans: red, green, blue order
  8. # channels are swapped
  9. print(img_bgr[0, 0]) # [B, G, R]
  10. print(img_rgb[0, 0]) # [R, G, B]
  11. #ans: values are in different order

RGB to Grayscale

  1. # convert to grayscale
  2. img = cv2.imread('image.jpg')
  3. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  4. #ans: single channel intensity
  5. print(gray.shape)
  6. #ans: (height, width) - no channel dimension
  7. # grayscale formula (weighted average)
  8. # Gray = 0.299*R + 0.587*G + 0.114*B
  9. #ans: green weighted more (human eye sensitivity)

Converting to HSV

  1. # convert to HSV
  2. img = cv2.imread('image.jpg')
  3. hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
  4. #ans: hue, saturation, value
  5. # split HSV channels
  6. h, s, v = cv2.split(hsv)
  7. #ans: separate channels
  8. print(h.shape)
  9. #ans: (height, width)
  10. # HSV ranges in OpenCV
  11. #ans: H: 0-179, S: 0-255, V: 0-255

Color Thresholding in HSV

  1. # detect red objects using HSV
  2. hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
  3. # define red color range (hue wraps around)
  4. lower_red = np.array([0, 100, 100])
  5. upper_red = np.array([10, 255, 255])
  6. #ans: hue 0-10 is red, high saturation/value
  7. mask = cv2.inRange(hsv, lower_red, upper_red)
  8. #ans: binary mask where red regions are 255
  9. # apply mask to extract red objects
  10. result = cv2.bitwise_and(img, img, mask=mask)
  11. #ans: keeps only red regions

Split & Merge Channels

  1. # split BGR channels
  2. b, g, r = cv2.split(img)
  3. #ans: separate B, G, R channels (each is grayscale)
  4. # merge channels back
  5. merged = cv2.merge([b, g, r])
  6. #ans: reconstructs original image
  7. # swap red and blue channels
  8. swapped = cv2.merge([r, g, b])
  9. #ans: BGR becomes RGR (looks different!)

LAB Color Space

  1. # convert to LAB
  2. img = cv2.imread('image.jpg')
  3. lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
  4. #ans: L (lightness), a, b (color opponents)
  5. l, a, b = cv2.split(lab)
  6. #ans: L is grayscale-like luminance
  7. # LAB advantages
  8. #ans: perceptually uniform (distance = perceived difference)
  9. #ans: useful for color correction, white balance

Exercises - Part 1 (Concepts)

  1. # what does cvtColor do?
  2. rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  3. #ans: converts between color spaces
  4. # why use HSV for color detection?
  5. #ans: separates color (H) from lighting (V), easier thresholding
  6. # what is the output dimensions?
  7. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  8. print(gray.ndim)
  9. #ans: 2 (2D array, loses channel dimension)
  10. # what color space does OpenCV use by default?
  11. img = cv2.imread('image.jpg')
  12. #ans: BGR (blue, green, red)

Exercises - Part 2 (Concepts)

  1. # which channel is most important for grayscale?
  2. # Gray = 0.299*R + 0.587*G + 0.114*B
  3. #ans: green (0.587 = highest weight)
  4. # what is hue range in OpenCV?
  5. #ans: 0-179 (represents 0-360°, divided by 2)
  6. # when to use LAB color space?
  7. #ans: color correction, perceptual uniformity, white balance
  8. # what does inRange return?
  9. mask = cv2.inRange(hsv, lower, upper)
  10. #ans: binary mask (0 or 255) where values in range

Exercises - Part 3 (Coding)

  1. # convert BGR to RGB
  2. img_bgr = cv2.imread('img.jpg')
  3. img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
  4. #ans: swaps red and blue channels
  5. # extract red channel from RGB
  6. r = img_rgb[:, :, 0]
  7. #ans: red channel (first in RGB)
  8. # create red-only image
  9. red_only = img_rgb.copy()
  10. red_only[:, :, 1:] = 0
  11. #ans: green and blue set to 0, keeps red

Exercises - Part 4 (Coding)

  1. # detect blue color in HSV
  2. hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
  3. lower_blue = np.array([100, 50, 50])
  4. upper_blue = np.array([130, 255, 255])
  5. mask = cv2.inRange(hsv, lower_blue, upper_blue)
  6. #ans: binary mask of blue regions
  7. # apply mask to image
  8. result = cv2.bitwise_and(img, img, mask=mask)
  9. #ans: extracts blue regions only
  10. # invert mask
  11. inv_mask = cv2.bitwise_not(mask)
  12. #ans: inverts binary mask (0→255, 255→0)

Exercises - Part 5 (Mixed)

  1. # swap red and blue channels
  2. b, g, r = cv2.split(img)
  3. swapped = cv2.merge([r, g, b])
  4. #ans: creates RGB from BGR
  5. # extract hue channel
  6. hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
  7. hue = hsv[:, :, 0]
  8. #ans: hue values (0-179 in OpenCV)
  9. # what happens here?
  10. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  11. back = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)
  12. #ans: grayscale image with 3 identical channels
  13. # are original and back the same?
  14. #ans: no, back lost color information (all channels same)

Google tag (gtag.js)