A perceptual color space is desirable when doing many kinds of image processing. It is useful for things like:
Unfortunately, as far as I am aware, while there are color spaces that aim to be perceptually uniform, none are without significant drawbacks when used for image processing.
For this reason I have designed a new perceptual color space, designed to be simple to use, while doing a good job at predicting perceived lightness, chroma and hue. It is called the Oklab color space, because it is an OK Lab color space.
Before diving into the details of why a new color space is needed and how it was derived, here is the everything needed to use the color space:
Here is a list of Oklab implementations that I am aware of. The list will be updated as I’m made aware of more implementation. These are all implemented by other people and I have not verified their correctness myself.
- Python – Colour, colorio
- Javascript – culori
- TypeScript – thi.ng/color
- C++ – farver
- Matlab – Geometry Processing Toolbox
- Java – colorful-gdx
- Various – G’MIC
There are also a few experiments available to play around with Oklab online at Observable and Shadertoy
A color in Oklab is represented with three coordinates, similar to how CIELAB works, but with better perceptual properties. Oklab uses a D65 whitepoint, since this is what sRGB and other common color spaces use. The three coordinates are:
For many operations, Lab-coordinates can be used directly, but they can also be transformed into polar form, with the coordinates lightness, chroma and hue, LCh:
C=√,h=atan2(b,a)
Lets look at a practical example to see how Oklab performs, before looking at how the Lab coordinates are computed.
Here’s an Oklab color gradient with varying hue and constant lightness and chroma.
Compare this to a similar plot of a HSV color gradient with varying hue and constant value and saturation (HSV using the sRGB color space).
The gradient is quite uneven and there are clear differences in lightness for different hues. Yellow, magenta and cyan appear much lighter than red and blue.
Here is lightness of the HSV plot, as predicted by Oklab:
Given a color in XYZ coordinates, with a D65 whitepoint and white as Y=1, Oklab coordinates can be computed like this:
A non-linearity is applied:
\begin{pmatrix} l' \\ m' \\ s' \end{pmatrix} = \begin{pmatrix} l^{\frac 1 3} \\ m^{\frac 1 3} \\ s^{\frac 1 3} \end{pmatrix}=
\begin{pmatrix} L \\ a \\ b \end{pmatrix} = \mathbf{M_2} \times \begin{pmatrix} l' \\ m' \\ s' \end{pmatrix}=M×
M=
M=
The inverse operation, going from Oklab to XYZ is done with the following steps: