Colors

Color Space

Color is a human perception and describes the visible spectrum of light that is reflected off the surface of any object. With the advancement of computers, we went from monochrome to color displays. This led the industry to come up with different ways to tell the computer what is “color”. Consequently the many “Color Space” has emerged. When working with images there are 3-4 most commonly used color spaces. In our earlier post on “How to load and save images”, we already saw some of them. For instance, greyscale (black and white) images has “color” represented as a numerical value normally between 0 to 255 (8bit). Another color space we’ve encountered in the past is RGB (Red Green Blue), or in  OpenCV BGR (Blue Green Red). Finally today  we would like to introduce a fourth commonly used color space; namely HSV (Hue Saturation Value).

Color space – Hue Saturation Value (HSV)

HSV as the name implies stores the value of color as a 3-tuple. H stands for Hue and is a single value to represent color from 0 to 360. Owing to this, Hue can be described as a circle based on its degree. S stands for Saturation (or sometimes called Chroma) and can also be described as how “gray” the color is. Finally V stands for Value or sometimes referred to as Brightness. Brightness as the name implies describes how white (bright) or black (dark) the color is. To illustrate and better visualize HSV, we visualize it as cone.

Color Space - HSV color solid cone chroma gray
Source: Wikipedia – Color Space – HSV color solid cone chroma gray

Advantages of using HSV

In view of several color spaces available to chose from, why would we introduce another one? In order to answer this question, we need to look back at RGB. Important to note is RGB uses all three channels in combination to represent color. As a result, dependent on the lighting conditions, the RGB values can fluctuate dramatically. In comparison, as HSV isolates color (Hue) from brightness, the Hue is less subject to fluctuations due to lighting conditions. To demonstrate this we show two pictures taken at different times of day.

Color Space - Highway 7 and McCowan Rd in York Region Ontario - Day time
Image Source: York Region Traffic Cameras
Color Space - Highway 7 and McCowan Rd in York Region Ontario - Night time
Image Source: York Region Traffic Cameras

At this point we focus on the large patch of grass on the lower left of the image with the color picker displaying both RGB and HSV values on the same pixel. Notice how all RGB values displayed a large fluctuation of 30-65 (out of 256). In contrast, the Hue value of HSV only fluctuated by roughy 15 degrees (out 360). In other words, using RGB values the color fluctuated by about 17% while the Hue value only fluctuated by 4%.

Converting images between Color Space

Now that we understand why it may be advantageous to use HSV, the obvious question is how to convert images between color spaces. First we import the necessary libraries and optional function for displaying images in Jupyter notebooks and our image.

import cv2
import numpy as np

#Load our image
image = cv2.imread("Hwy7McCowan Day Colorpicker.png")

#The lines below is only necessary to show Matplotlib's plots inside a Jupyter Notebook
%matplotlib inline

from matplotlib import pyplot as plt

#Use this helper function if you are working in Jupyter Lab
#If not, then directly use cv2.imshow(<window name>, <image>)

def showimage(myimage):
    if (myimage.ndim>2):  #This only applies to RGB or RGBA images (e.g. not to Black and White images)
        myimage = myimage[:,:,::-1] #OpenCV follows BGR order, while matplotlib likely follows RGB order
        
    fig, ax = plt.subplots(figsize=[10,10])
    ax.imshow(myimage, cmap = 'gray', interpolation = 'bicubic')
    plt.xticks([]), plt.yticks([])  # to hide tick values on X and Y axis
    plt.show()

As an initial demonstration, we convert between BGR (the default representation in OpenCV) to grayscale

#Convert BGR to Grayscale
imagegray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
showimage(imagegray)
Color Space - Converting to Grayscale

Next, we convert our image from BGR to HSV.

# Convert image to HSV
imageHSV = cv2.cvtColor(image,cv2.COLOR_BGR2HSV)
showimage(imageHSV)
Color Space - Converting to HSV

As shown above, using only a single line of code will allow us to convert the image between different color spaces. There are many additional options provided by OpenCV in cvtColor for color conversion at your disposal. As a last topic, we explore how HSV stored in python. To demonstrate this, we take the RGB values shown in our day time picture.

# We first take the same RGB values as shown from our Color Picker and record them in BGR
grass = np.uint8([[[66,118,101]]])

# Next we convert the values to HSV as before
hsv_grass = cv2.cvtColor(grass,cv2.COLOR_BGR2HSV)

# Finally print out converted values
print(hsv_grass)
[[[ 40 112 118]]]

Evident from our original image, we expect the answer to come to (79.6, 44.1%, and 46.3%). Most important to note, HSV is stored as follows:

  • H = [0:179] – In order to fit 360 degrees into 8 bit integer, the values are divided by 2 (e.g. 360/2)
  • S = [0:255]
  • V = [0:255]

In conclusion, with some simple math, we can see that H=40 is equivalent to 80 degrees. Likewise S=112/256 = 44% and V=118/256 = 46%. Obviously, by using 8 bit integers we can experience information lost due to rounding. A conversion into fp32 would help alleviate the issue if color accuracy is of utmost importance.

FreedomvcAbout Alan Wong
Alan is a part time Digital enthusiast and full time innovator who believes in freedom for all via Digital Transformation. 
兼職人工智能愛好者,全職企業家利用數碼科技釋放潛能與自由。

LinkedIn

Leave a Reply