# How to Compute Perceptual Color Difference

I wrote previously about the new `colorChecker`, which can detect X-Rite test charts in the R2020b release. Another area of new color-related functionality is computing perceptual color differences. There is the new function `deltaE`, which computes color differences based on the L*a*b* color space and the CIE76 standard. There is also the `imcolordiff` function, which can compute color differences based either on the CIE94 or the CIEDE2000 standard.

I recently mentioned to someone on the Image Processing Toolbox team that I was planning to write a blog post about these functions, and he posed the following question: which two colors are the furthest apart, perceptually speaking? I decided to give that a try using $\Delta_E$. I'll formulate the problem this way: which two sRGB colors have the largest $\Delta_E$ between them?

In a related post back in 2015, I demonstrated how to plot the sRGB gamut surface in L*a*b* space, like this:

Looking at this diagram, you might be able to guess the answer. But, let's work through it. The first thing I want to do is to sample the sRGB space.

[r,g,b] = ndgrid(linspace(0,1,100)); rgb = [r(:), g(:), b(:)];

Next, convert the sRGB colors to Lab. (I'm going to stop typing the "*" characters.)

lab = rgb2lab(rgb);

Now let's find the colors on the convex hull of the Lab values. The pair of colors most distant from each other must both be on the convex hull.

k = convhull(lab); hull_colors = lab(unique(k(:,1)),:);

If this were a two-dimensional problem, then I know of an algorithm that can find the most distant pair of points in $O(N)$, where $N$ is the number of points on the convex hull. I don't know of a similar algorithm in three dimensions, so I'm just going to brute force it by computing the distance between every color pair.

So, how many colors are we talking about?

size(hull_colors)

ans = 3980 3

There are 3908 colors, each of which is represented by a 3-element vector in Lab space. The color difference $\Delta_E$ is the Euclidean distance between two colors in Lab space. I want to compute the distance between every color in that set and every other color. Here is a nifty and compact way to do that using the implicit expansion behavior of MATLAB arithmetic operators.

C1 = reshape(hull_colors,[],1,3); C2 = reshape(hull_colors,1,[],3); Cdiff = C1 - C2; DE = sqrt(sum(Cdiff.^2,3)); size(DE)

ans = 3980 3980

You can see that `DE` is an 3980x3980 matrix. It contains the pair-wise distances between all the convex hull colors. (See also `pdist2`, a function in the Statistics and Machine Learning Toolbox that can compute pair-wise vector distances with much more flexibility, as well as `hypot`, a MATLAB function that computes the magnitude of a two-element vector in a way that avoids numerical overflow and underflow problems.)

Let's find where the maximum distances are in this matrix.

[m,n] = find(DE == max(DE(:)))

m = 3883 92 n = 92 3883

What are those colors (in Lab space)?

max_colors_lab = hull_colors(m,:)

max_colors_lab = 32.2970 79.1875 -107.8602 87.7347 -86.1827 83.1793

And those two colors in sRGB space:

max_colors_rgb = lab2rgb(max_colors_lab)

max_colors_rgb = 0.0000 -0.0000 1.0000 0.0000 1.0000 0.0000

They are just the sRGB green and blue primaries.

colorSwatches(max_colors_rgb) axis equal axis off

(`colorSwatches` is a **DIPUM3E** function that is available to you in *MATLAB Color Tools* on the File Exchange and on GitHub.)

These two colors have a $\Delta_E$ of:

DE(m(1),n(1))

ans = 258.6827

The deltaE function offers a more convenient way to compute $\Delta_E$:

deltaE([0 1 0],[0 0 1])

ans = 258.6827

Some other time, I will write about the other color difference calculations provided by `imcolordiff`.

## Comments

To leave a comment, please click here to sign in to your MathWorks Account or create a new one.