color_tools.distance

Color distance metrics for measuring perceptual color differences.

Includes multiple Delta E formulas: - Delta E 1976 (CIE76): Simple Euclidean distance - Delta E 1994 (CIE94): Improved with weighting - Delta E 2000 (CIEDE2000): Current gold standard - Delta E CMC: Textile industry standard

Also includes simpler distance functions for RGB and HSL spaces.

Example

>>> from color_tools import rgb_to_lab, delta_e_2000
>>>
>>> # Compare two similar reds
>>> red1 = rgb_to_lab((255, 0, 0))    # Pure red
>>> red2 = rgb_to_lab((250, 5, 5))    # Slightly darker red
>>>
>>> # Calculate perceptual difference
>>> distance = delta_e_2000(red1, red2)
>>> print(f"ΔE2000: {distance:.2f}")
ΔE2000: 2.85
>>>
>>> # ΔE < 1.0 = imperceptible
>>> # ΔE < 2.0 = barely noticeable
>>> # ΔE < 5.0 = noticeable but acceptable
>>> if distance < 2.0:
...     print("Colors are nearly identical!")
... elif distance < 5.0:
...     print("Colors are similar")
... else:
...     print("Colors are noticeably different")
Colors are similar
color_tools.distance.euclidean(v1, v2)[source]

Simple Euclidean distance between two vectors.

The classic √((x₁-x₂)² + (y₁-y₂)² + (z₁-z₂)²) formula. Works for any dimensionality, not just colors!

Parameters:
Return type:

float

color_tools.distance.hue_diff_deg(h1, h2)[source]

Calculate hue difference accounting for circular nature (0° = 360°).

Hue is circular (like a clock), so the difference between 359° and 1° should be 2°, not 358°! This function finds the smallest angular difference.

Parameters:
  • h1 (float) – Hue angles in degrees

  • h2 (float) – Hue angles in degrees

Return type:

float

Returns:

Smallest hue difference in degrees (0-180)

color_tools.distance.hsl_euclidean(hsl1, hsl2)[source]

Euclidean distance in HSL space (accounting for hue circularity).

Note: HSL distance doesn’t match human perception well - LAB is better! This is here for compatibility with systems that work in HSL.

Parameters:
Return type:

float

color_tools.distance.delta_e_76(lab1, lab2)[source]

Delta E 1976 (CIE76) - Simple Euclidean distance in LAB space.

The OG color difference formula! Just treats LAB like any other 3D space and measures straight-line distance.

Pros: Fast and simple Cons: Doesn’t match human perception well, especially for saturated colors

A ΔE of 1.0 is supposedly the “just noticeable difference” but in reality it varies based on the colors involved.

Parameters:
Return type:

float

Returns:

Delta E 1976 value (lower = more similar)

color_tools.distance.delta_e_94(lab1, lab2, kL=1.0, kC=1.0, kH=1.0, K1=None, K2=None)[source]

Delta E 1994 (CIE94) - Improved perceptual uniformity.

CIE94 realized that humans are more sensitive to lightness differences than chroma differences, and more sensitive to chroma than hue. This formula weights things accordingly!

Better than CIE76 but still has issues with saturated colors.

Parameters:
  • lab1 (Tuple[float, float, float]) – L*a*b* color tuples

  • lab2 (Tuple[float, float, float]) – L*a*b* color tuples

  • kL (float) – Weighting factors (usually all 1.0)

  • kC (float) – Weighting factors (usually all 1.0)

  • kH (float) – Weighting factors (usually all 1.0)

  • K1 (float | None) – Chroma and hue weighting constants (use defaults if None)

  • K2 (float | None) – Chroma and hue weighting constants (use defaults if None)

Return type:

float

Returns:

Delta E 1994 value (lower = more similar)

color_tools.distance.delta_e_2000(lab1, lab2, kL=1.0, kC=1.0, kH=1.0)[source]

Delta E 2000 (CIEDE2000) - Current gold standard for color difference.

This is THE formula to use for color matching! After decades of research, CIEDE2000 finally handles all the edge cases that tripped up earlier formulas: - Neutral colors (low chroma) - Blue hues (which humans perceive differently) - Lightness differences at different brightness levels

The formula is… complex. It’s got rotation terms, weighting functions, and special handling for different hue regions. But it WORKS!

Fun fact: A ΔE2000 of 1.0 is roughly the “just noticeable difference” for most colors. ΔE < 2 is considered imperceptible for most applications.

Parameters:
  • lab1 (Tuple[float, float, float]) – L*a*b* color tuples

  • lab2 (Tuple[float, float, float]) – L*a*b* color tuples

  • kL (float) – Weighting factors (usually all 1.0) - kL for lightness - kC for chroma - kH for hue

  • kC (float) – Weighting factors (usually all 1.0) - kL for lightness - kC for chroma - kH for hue

  • kH (float) – Weighting factors (usually all 1.0) - kL for lightness - kC for chroma - kH for hue

Return type:

float

Returns:

Delta E 2000 value (lower = more similar)

color_tools.distance.delta_e_cmc(lab1, lab2, l=2.0, c=1.0)[source]

Delta E CMC(l:c) - Color difference formula used in textile industry.

CMC was developed specifically for textile color matching, where the context matters (viewing conditions, material properties, etc.).

The l:c ratio lets you tune the formula for different use cases: - CMC(2:1) - “Acceptability” → Used to judge if colors match well enough - CMC(1:1) - “Perceptibility” → More strict, for detecting differences

Why two ratios? Turns out humans are more forgiving of color differences when deciding “is this acceptable?” vs “can I see a difference?”

Parameters:
Return type:

float

Returns:

Delta E CMC value (lower = more similar)