Skip to content

Color Distance and Delta E

The difference or distance between two colors allows for a quantified analysis of how far apart two colors are from one another. This metric is of particular interest in the field of color science, but it has practical applications in color libraries working with colors.

Usually, color distance is applied to near perceptual uniform color spaces in order to obtain a metric regarding a color's visual, perceptual distance from another color. This can be useful in gamut mapping or even determining that colors are close enough or far enough away from each other.

Color Distance

ColorAide provides a simple euclidean color distance function. By default, it evaluates the distance in the CIELab color space, but it can be configured to evaluate in any color space, such as Oklab, etc. It may be less useful in some color spaces compared to others. Cylindrical spaces with polar coordinates will be converted to rectangular coordinates if specified. Some spaces might not be as very perceptually uniform.

>>> Color("red").distance("blue", space="srgb")
1.4142135623730951
>>> Color("red").distance("blue", space="lab")
184.0190486209969

New 3.3

Handling spaces with polar coordinates is new in 3.3.

Delta E

The delta_e function gives access to various ∆E implementations, which are just different algorithms to calculate distance. Some are simply Euclidean distance withing a certain color space, some are far more complex.

If no method is specified, the default implementation is ∆E*ab (CIE76) which uses a simple Euclidean distancing algorithm on the CIELab color space. It is fast, but not as accurate as later iterations of the algorithm as CIELab is not actually as perceptually uniform as it was thought when CIELab was originally developed.

>>> Color("red").delta_e("blue")
176.3084955965824

When method is set, the specified ∆E algorithm will be used instead. For instance, below we use ∆E*00 which is a more complex algorithm that accounts for the CIELab's weakness in perceptually uniformity. It does come at the cost of being a little slower.

>>> Color("red").delta_e("blue", method="2000")
52.87819528592645

Distancing and Symmetry

It should be noted that not all distancing algorithms are symmetrical. Some are order dependent.

Delta E CIE76

The ∆Eab distancing algorithm is registered in Color by default

Delta E Symmetrical Name Parameters
∆E*ab (CIE76) 76 space='lab-d65'

One of the first approaches to color distancing and is actually just Euclidean distancing in the CIELab color space.

Note

By default, Lab D65 is used for color distancing. In the print industry, it is common for Lab D50 to be used. If Lab D50 is desired, simply specify it as the space color space. space must be a CIE Lab color space.

>>> Color("red").delta_e("blue", method="76")
176.3084955965824
>>> Color("red").delta_e("blue", method="76", space='lab')
184.0190486209969

Delta E CMC (1984)

The ∆Ecmc distancing algorithm is registered in Color by default

Delta E Symmetrical Name Parameters
∆E*cmc (CMC l:c (1984)) cmc l=2, c=1, space='lab-d65'

Delta E CMC is based on the CIELCh color space. The CMC calculation mathematically defines an ellipsoid around the standard color with semi-axis corresponding to hue, chroma and lightness.

Parameter Acceptability Perceptibility
l 2 1
c 1 1

Note

By default, Lab D65 is used for color distancing. In the print industry, it is common for Lab D50 to be used. If Lab D50 is desired, simply specify it as the space color space. space must be a CIE Lab color space.

>>> Color("red").delta_e("blue", method="cmc")
108.56925233888809
>>> Color("red").delta_e("blue", method="cmc", space='lab')
114.2301281201658

Delta E CIE94

The ∆E*94 distancing algorithm is registered in Color by default

Delta E Symmetrical Name Parameters
∆E*94 (CIE94) 94 kl=1, k1=0.045, k2=0.015, space='lab-d65'

The 1976 definition was extended to address perceptual non-uniformities, while retaining the CIELab color space, by the introduction of application-specific weights derived from an automotive paint test's tolerance data.

Parameter Graphic Arts Textiles
kl 1 2
k1 0.045 0.048
k2 0.015 0.014

Note

By default, Lab D65 is used for color distancing. In the print industry, it is common for Lab D50 to be used. If Lab D50 is desired, simply specify it as the space color space. space must be a CIE Lab color space.

>>> Color("red").delta_e("blue", method="94")
70.57699903580162
>>> Color("red").delta_e("blue", method="94", space='lab')
73.82677591958294

Delta E CIEDE2000

The ∆E*00 distancing algorithm is registered in Color by default

Delta E Symmetrical Name Parameters
∆E*00 (CIEDE2000) 2000 kl=1, kc=1, kh=1, space='lab-d65'

Since the 1994 definition did not adequately resolve the perceptual uniformity issue, the CIE refined their definition, adding five corrections:

  • A hue rotation term (RT), to deal with the problematic blue region (hue angles in the neighborhood of 275°)
  • Compensation for neutral colors (the primed values in the LCh differences)
  • Compensation for lightness (SL)
  • Compensation for chroma (SC)
  • Compensation for hue (SH)

Note

By default, Lab D65 is used for color distancing. In the print industry, it is common for Lab D50 to be used. If Lab D50 is desired, simply specify it as the space color space. space must be a CIE Lab color space.

>>> Color("red").delta_e("blue", method="2000")
52.87819528592645
>>> Color("red").delta_e("blue", method="2000", space='lab')
55.79977339019779

Delta E HyAB

The ∆EHyAB distancing algorithm is registered in Color by default

Delta E Symmetrical Name Parameters
∆EHyAB (HyAB) hyab space="lab-d65"

A combination of a Euclidean metric in hue and chroma with a city‐block metric to incorporate lightness differences. It can be used on any Lab like color space, the default being CIELab D65.

Delta E OK

The ∆Eok distancing algorithm is registered in Color by default

Delta E Symmetrical Name Parameters
∆Eok ok scalar=1

A color distancing algorithm that performs Euclidean distancing in the Oklab color space. This is used in the OkLCh Chroma gamut mapping algorithm. The scalar parameter allows you to scale the result up if desired.

Delta E ITP

The ∆Eitp distancing algorithm is registered in Color by default

Delta E Symmetrical Name Parameters
∆Eitp (ICtCp) itp scalar=720

Various algorithms are designed for and perform decently in the SDR range, but ∆Eitp aims to provide good distancing in the HDR range using the ICtCp color space (must be registered in order to use ∆Eitp). It was determined that a scalar of 240 was more comparable to the average ∆E*00 result from the JND data set and 720 equates them to a JND.

Delta E Z

The ∆Ez distancing algorithm is registered in Color by default

Delta E Symmetrical Name Parameters
∆Ez (Jzazbz) jz

Performs Euclidean distancing in the Jzazbz color space, useful for the HDR range.

Delta E 99o

The ∆E99o distancing algorithm is not registered in Color by default

Delta E Symmetrical Name Parameters
∆E99o (DIN99o) 99o

∆E99o performs Euclidean distancing in the DIN99o color space.

Both the DIN99o color space and the ∆E algorithm must be registered to use.

from coloraide import Color as Base
from coloraide.distance.delta_e_99o import DE99o
from coloraide.spaces.din99o import DIN99o

class Color(Base): ...

Color.register([DIN99o(), DE99o()])

Delta E CAM16

The ∆Ecam16 distancing algorithm is not registered in Color by default

Delta E Symmetrical Name Parameters
∆Ecam16 cam16 model='ucs'

The CAM16 UCS uniform color space applies an additional nonlinear transformation to lightness and colorfulness so that a color difference metric ΔE can be based more closely on Euclidean distance. This algorithm performs distancing using the CAM16 UCS color space. If desired model can be changed to use the SCD or LCD model for "small" and "large" distancing respectively

Parameter Default Description
space cam16-ucs The CAM16 color space derived from the CAM16UCS space. cam16-ucs, cam16-scd, and cam16-lcd are provided in ColorAide (unregistered by default). Variants using different lighting environments can be created and registered and provided as the UCS space to operate in.

Deprecated model parameter

In 3.3 the model parameter was deprecated and will be removed at some future time. space is more flexible and should be used instead.

The one or more of the CAM16 (UCS/SCD/LCD) color spaces and the ∆E algorithm must be registered to use.

from coloraide import Color as Base
from coloraide.distance.delta_e_cam16 import DECAM16
from coloraide.spaces.cam16_ucs import CAM16UCS, CAM16SCD, CAM16LCD

class Color(Base): ...

Color.register([CAM16UCS(), CAM16SCD(), CAM16LCD(), DECAM16()])

Delta E HCT

The ∆Ehct distancing algorithm is not registered in Color by default

Warning

This approach was specifically added to help produce tonal palettes, but with the recent addition of the ray trace approach to chroma reduction in any perceptual space, users can defer to the ray tracing approach which does not require a special ∆E method and it performs much faster.

On occasions, MINDE approach can be slightly more accurate very close to white due to the way ray trace handles HCT's atypical achromatic response, but differences should be imperceptible to the eye at such lightness levels making the the improved performance of the ray trace approach much more desirable.

>>> c = Color('hct', [325, 24, 50])
>>> tones = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 100]
>>> Steps([c.clone().set('tone', tone).convert('srgb').to_string(hex=True, fit={'method': 'raytrace', 'pspace': 'hct'}) for tone in tones])
['#000000', '#29132e', '#3f2844', '#573e5b', '#705574', '#8a6d8d', '#a587a8', '#c1a1c3', '#debcdf', '#fbd7fc', '#ffebfd', '#ffffff']
Delta E Symmetrical Name Parameters
∆EHCT hct

This takes the HCT color space C and H components (CAM16's M and h) and converts them to CAM16 UCS M and h, and applies Euclidean distancing on them along with the T component (CIELab's L*). This is necessary for the HCT Chroma gamut mapping approach.

from coloraide import Color as Base
from coloraide.distance.delta_e_hct import DEHCT
from coloraide.spaces.HCT import HCT

class Color(Base): ...

Color.register([HCT(), DEHCT()])

Finding Closest Color

ColorAide implements a simple way to find the closest color, given a list of colors, to another color. The method is called closest and takes a list of colors that are to be compared to the calling color object. The first color with the smallest distance between the calling color object and itself will be considered the nearest/closest color.

Consider the following example. Here we provide a list of colors to compare against red. After comparing all the colors, the closest ends up being maroon.

>>> Color('red').closest(['pink', 'yellow', 'green', 'blue', 'purple', 'maroon'])
color(srgb 0.50196 0 0 / 1)

The default distancing method is used if one is not supplied, but others can be used:

>>> Color('red').closest(['pink', 'yellow', 'green', 'blue', 'purple', 'maroon'], method='2000')
color(srgb 0.50196 0 0 / 1)

Configuring Delta E Defaults

A number of distancing algorithms have configurable features that can be set on demand. If you'd like to have these options set by default, you create a custom class and register the the plugins with the defaults of your choice.

In this example, we will configure ∆E*00 to use CIE Lab D50 instead of D65 by default.

>>> from coloraide import Color as Base
>>> from coloraide.distance.delta_e_2000 import DE2000
>>> class Color(Base):
...     ...
... 
>>> Color.register(DE2000(space='lab'), overwrite=True)
>>> Color('red').delta_e('blue', method='2000')
55.79977339019779
>>> Color('red').delta_e('blue', method='2000', space='lab-d65')
52.87819528592645