Blog

[Fun Project] Label Random Colors Based on Hue

28 February 2023

I drew a square and filled it with random colors. With help from the hue, I labeled the color of that square.

Have you ever wondered how computers can recognize and interpret colors? It can use complex algorithms and training to identify color (like this example) or use hue.

Hue is part of the HSV (Hue, Saturation, and Value) model that defines the color portion [link]. It is often expressed as a degree between 0 to 360 or as a number between 0 to 1.0 on the HSV color wheel. We can determine whether something is blue, green, yellow, or any other color by looking at its position on the wheel. For example, if a particular hue falls between 0 and 8 degrees, we can guess it is a red shade.

For this project, I categorized the hue based on this reference. They use 16 color labels, e.g., red, red-orange, yellow-green, and blue. For the hue range, I refer to the hue value on their table.

Green color’s red, green, blue, hex, luminance, hue, saturation, and lightness from the reference.

For example, the highest hue for green color is 138, so I start the following color (green-cyan) from 139. Please refer to the color wheel below for a better illustration.

Hue color wheel.

However, while using hue is practical, we must admit that the categorization is limited. By leaving the “value” out, we lose the brightness data from the color system; we do not have the white and black category since both colors can be composed of various hues.

The red and blue color above has a hue of 3o and 237o, but the same low value of 9% makes both colors look dark (black).

Compared to eye observation, the hue interpretation is sometimes inaccurate. Utilizing a single parameter and lacking learning for the hue range may cause this imperfection.

The hue of the above color falls in a blue shade, but my eye sees it as blue-magenta.

Program Blocks

This project was done in Python using the turtle to draw graphics into the screen and the colorsys library to convert RGB to HSV color system, and broken down into five steps.

  1. Set up the screen for displaying a square and its label.
  2. Create a square and fill it with a random color.
  3. Convert the color to the HSV color system and label it based on the hue category on the hue color wheel.
  4. Create text that shows a color label.
  5. Until we terminate it, loop the program to keep changing the square’s color and showing the label.

Three files were created:

  1. main.py as the main file
  2. square.py to hold the Square class that defines a square and has a function to change color, and
  3. color_guessr.py to hold ColorGuessr class that categorizes the color and prints the label

Set Up the Screen

First, I created a new screen, 600px-by-600px in size.

main.py

from turtle import Screen

screen = Screen()
screen.setup(600, 600) # width = 600px, height = 600px
screen.tracer(0)       # automatic screen updates are off

Create a Square

I created a square using the turtle library. I prepared the square in a class named Square that inherited the properties of the turtle library. I stretched the size of the square to make it bigger using the “shapesize” function.

My turtle had a color mode of 1.0. Hence, to initialize the square color to white (the color with the highest value), I set the red, green, and blue spectrum in the RGB color system to 1.

Next, to change the color, I utilized the random library. Whenever we call it, the change_color() function generates a random value for each red, green, and blue spectrum.

square.py

import random
from turtle import Turtle

class Square(Turtle):
    def __init__(self):
        super().__init__()
        self.shape("square")
        self.shapesize(stretch_wid=10, stretch_len=10)
        self.goto(0, 40)
        self.color_r = 1
        self.color_g = 1
        self.color_b = 1
        self.color(self.color_r, self.color_g, self.color_b)

    def change_color(self):
        self.color_r = random.random()
        self.color_g = random.random()
        self.color_b = random.random()
        self.color(self.color_r, self.color_g, self.color_b)

main.py

from square import Square
...
# Create a square
square = Square()
...
# Change square's color
square.change_color()

Define Color Label

This block was pretty straightforward. Using the colorsys library, I converted the RGB to the HSV color system. Then, I took the first item in the HSV color system to get the hue. Since the color was in 1.0 color mode, to get a maximum hue degree of a full rotation, I multiplied the hue by 360. Last, the hue was segmented based on the range illustrated in the color wheel.

color_guessr.py

import colorsys

    ...
    def guess_color(self, r, g, b):
        self.color_r = r
        self.color_g = g
        self.color_b = b
        
        # Convert RGB to HSV
        color_hsv = colorsys.rgb_to_hsv(self.color_r, self.color_g, self.color_b)

        # Get the hue from HSV
        hue = color_hsv[0] * 360

        # Categorize the hue, label the color 
        if hue < 8:
            self.guess = "red"
        elif hue < 21:
            self.guess = "red-orange"
        elif hue < 40:
            self.guess = "orange & brown"
        elif hue < 52:
            self.guess = "orange-yellow"
        elif hue < 61:
            self.guess = "yellow"
        elif hue < 81:
            self.guess = "yellow-green"
        elif hue < 139:
            self.guess = "green"
        elif hue < 169:
            self.guess = "green-cyan"
        elif hue < 200:
            self.guess = "cyan"
        elif hue < 220:
            self.guess = "cyan-blue"
        elif hue < 246:
            self.guess = "blue"
        elif hue < 276:
            self.guess = "blue-magenta"
        elif hue < 316:
            self.guess = "magenta"
        elif hue < 341:
            self.guess = "magenta-pink"
        elif hue < 351:
            self.guess = "pink"
        elif hue < 356:
            self.guess = "pink-red"
        else:
            self.guess = "red"

Show Color Label

Like the Square class, ColorGuessr class inherits the properties from the turtle library. In the initialization, I hid the icon for the turtle but wrote the color label at the turtle position. Then, I set the turtle’s position below the square with help from the goto() function.

I created two functions inside the ColorGuessr class: guess_color() to define the color label (see the previous block) and print_guess(). The print_guess() function prints the label with a font color matching the square color.

The clear() function is inherited from the turtle library and is crucial to erase the label from the previous color before printing a new one.

color_guessr.py

from turtle import Turtle
import colorsys


class ColorGuessr(Turtle):
    def __init__(self):
        super().__init__()
        self.guess = "undefined"
        self.penup()
        self.hideturtle()
        self.color_r = 1
        self.color_g = 1
        self.color_b = 1
        self.goto(self.xcor(), self.ycor() - 120)

    # Define color label
    def guess_color(self, r, g, b):
        ...
        self.print_guess()

    def print_guess(self):
        self.clear()
        self.color(self.color_r, self.color_g, self.color_b)
        self.write((self.guess).capitalize(), font=("Arial", 40, "bold"), align="center")
Print color: magenta pink
The program shows a colored square and labels it as a magenta-pink.

Loop the Program

Finally, after creating the objects for both Square and ColorGuessr class, I concluded the main file by looping our objective: changing the square’s color with a random color and labeling that color.

Inside the loop, we also have time.sleep() function that controls how long we will wait before executing another loop.

main.py

from turtle import Screen
from square import Square
from color_guessr import ColorGuessr
import time


SLEEP_TIME = 1     # 1 second

# Set up screen
screen = Screen()
screen.setup(600, 600)
screen.title("?? What COLOR ??")
screen.tracer(0)

# Create a square
square = Square()

# Create a color guesser
guess = ColorGuessr()

while True:
    time.sleep(SLEEP_TIME)
    screen.update()

    # Change square's color
    square.change_color()

    # Print the square color
    guess.guess_color(square.color_r, square.color_g, square.color_b)

screen.exitonclick()

Complete Code and References

Complete code: GIT

References:


P.S. Want a more tangible way to play with color? Try a Reverse Coloring Book*; create lines for watercolor objects.

*As an Amazon Associate, I earn from qualifying purchases.

- Ilma Andayana