Home Articles Other Contact

Color Spaces and Even Color Spacing

< Previous

1 / 14 / 22

Next >

7 min read

TLDR (click to show/hide)

I came across the need to generate n-many unique-looking colors for a research project visualization. It turns out using the traditional RGB or HSV color models with random values is actually pretty bad at generating perceptually distinct colors. Digging a bit into the field of color science, this article comes across some models built for this sort of thing (CIE XYZ and CIE LAB) and discusses an approach that lets us get exactly the result we were looking for.

Hello! Hope everyone had a wonderful winter break.

I've finally wrapped up all my grad school applications and I've been able to spend some time learning React and thinking about a problem I encountered while making a game this past semester. The problem arose when I needed to come up with a bunch of unique random colors for objects in the game. It reminded me of Bertrand's Paradox in that depending on which color model we use to represent our colors, the amount of randomness in the results could vary widely.

Introduction to Color Science

Color science is the study of human perception of colors. In displaying colors on machines such as computer monitors, tv screens, and our phones, it can be very useful to have a mathematical description of colors. Color science gives us the idea of a color space, which is exactly the sort of mathematical model we want for this. Some common models you may be familiar with are RGB, HSV, and CMYK which describe colors as points in three or four dimensional space.

Visualizations of the RGB and HSV color models respectively

Generating Colors

Say we want a set of random colors to distinctively label some objects. Our first approach might just be choosing to use the standard HSV color model for artists and uniformly picking values for each of hue, saturation, and value. Doing this gives us the following:

Random colors created by uniformly sampling each of the hue, saturation, and value coordinates

This wasn't so great, a lot of the colors end up looking fairly similar which is exactly what we don't want to happen. The reason for this is that certain regions of the HSV color space have a lot of similarities. For example, if the value (brightness) is low, all of the colors will end up looking black, or if the saturation is low, all of the colors will look gray despite them having uniformly random hues.

Maybe if we use the RGB color model, we can get some better results:

Random colors created by uniformly sampling each of the red, green, and blue coordinates

This gave us significantly better results! This is where we can see the resemblance of our problem to Bertrand's Paradox. The randomness of our colors depends on the coordinate system to select them. The RGB colors are good, but there are still quite a few of them that are too close to one another. This begs the questions: what is the best space to use when generating colors?

The CIE LAB Color Space

One of the issues with the RGB and HSV models is that they are not perceptually uniform. That is, the euclidean distance between colors in these spaces isn't necessarily proportional with our perceived distance between the colors. This problem was addressed with the creation of CIE LAB by the International Commission on Illumination in 1976. Although its not particularly important for how we will be using the color space, I'd like to talk a bit about how it was created since I found it pretty interesting.

In 1931, the CIE RGB color space was created with the intention of getting a basis of colors which could be used to represent the entirety of the human percievable color space. This was done through great effort by having many test participants use varying levels of brightness of red, green, and blue light sources to match colors that were presented to them. The idea was that the three types of cone cells in our eyes roughly corresponding to red, green, and blue could be used to additively construct all colors we humans were able to see. The experiments ended with the following chart:

CIE RGB color component color functions

Notice that for some wavelengths, participants needed a 'negative' intensity of red light to reconstruct the color shown to them. This means that in order to match the target color, red had to be added to the target color to be able to get a percieved match. This tells us is that red, green, and blue alone are not able to constructively add to all of the possible colors in the visible spectrum.

Enter the CIE XYZ color space created in the same year as CIE RGB. X, Y, and Z represent three theoretical colors from which nonnegative values alone could be used to construct all possible wavelengths. Although shown in red, green, and blue below, X, Y, and Z are 'imaginary' colors constructed mathematically to give us this desired nonnegative property.

CIE XYZ color component color functions

From CIE XYZ, the CIE LAB color space was created in 1976 with these conversions between the coordinates. The idea for getting the space to be perceptually uniform was to look at a set of MacAdam Ellipses across the space. These ellipses are regions of a chromaticity diagram (a 2D slice of a color space with constant luminance) which consist of perceptually indistinguishable colors.

Conversion from CIE XYZ to the more perceptually uniform CIE LAB

Nice! Now we have a space where the euclidean distance between coordinate values representing the colors actually corresponds to our perceptual difference! (As a note, CIELAB is not perfectly perceptually uniform. Adjustments have been made to create slightly different colorspaces which do a better job of this, but CIELAB is still pretty good.)

Generating Colors Using CIE LAB

There are a few different methods we can try to get well spaced colors. If the goal is to maximize the minimum of the pairwise distances between colors we generate, the two best methods we could use are likely the ones covered in this article. Here, they use a method of repulsion in which each of the points in CIELAB representing a color push each other away with some force vector resulting in n maximally spaced colors. The other option they use in k-means clustering which also gives some nice results. Since both of these are already talked about there, I'd like to try something different.

In particular, instead of trying to maximize the distance between each of the colors, I want to see what a color pallete would look like with n evenly spaced colors. My idea for this is to select points on some lattice in CIELAB to get an array of colors which are perceptually the same distance apart from their adjacent colors in the pallete.

Lattice in the CIELAB colorspace

The gif above shows what we get when we look at the simple cubic lattice intersected with CIELAB. We can snake through the points in our lattice and lay out the colors associated with those points to see what our evenly spaced color pallete looks like:

Colors along a lattice in CIELAB

The resulting colors have a nice distinction to them. There are a few that feel a little close here because we generated so many, but because we are using CIELAB, we have a minimum guaranteed perceptual difference between any pair of colors.

I'm pretty satisfied with these results! The colors the generator is making are distinct enough for what I wanted to do with my other project and have a nice cohesiveness to them. I'd like to come back to this project in a future article though and see what happens when we intersect CIELAB with different lattices and surfaces and how the color palletes change when we apply transformations to these regions.

Thanks for reading!


Resources