Skip to content

Repository files navigation

Delta-EOK2

Abstract (TL;DR)

ΔEOK2 — ΔEOK with the Oklab a and b axes scaled by 2 — agrees with ΔE2000 noticeably better than ΔEOK does (r² 0.722 vs 0.642 on 5000 BT.2020 color pairs). Scaling the a/b axes by 2 is a measurable improvement, supporting Ottosson's recommendation. Repeating the same experiment in Oklrab — Oklab with a revised lightness estimate — gives the same story: ΔEOKr2 (r² 0.732) beats unscaled ΔEOKr (r² 0.613), and edges out ΔEOK2 slightly. The two lightness definitions perform about the same here; this dataset doesn't test viewing conditions (adaptive white), which is what Oklrab's lightness revision specifically targets.

Introduction

This repo compares the existing ΔEOK with ΔEOK2, a slightly modified version which scales the a and b axes by a factor of 2 as recommended by Björn Ottosson, inventor of Oklab:

Adjust the scaling of a&b to more accurately predict color distances

He also said

I unfortunately didn't spend that much time calculating and validating that scaling factor when I first derived Oklab since I was mostly focused on the orthogonality between L, C and h (and I didn't expect it to become so widespread so quickly), and it seems like it is off by quite a bit. I've recently done some tests with color distance datasets as implemented in Colorio and on both the Combvd dataset and the OSA-UCS dataset a scale factor of slightly more than 2 for a and b would give the best results (2.016 works best for Combvd and 2.045 for the OSA-UCS dataset).

Instead of changing the definition of Oklab, which is now widely adopted, this produces another distance metric ΔEOK2.

This repo examines the improvement this creates; both ΔEOK and ΔEOK2 are evaluated against ΔE2000 on a dataset of color pairs generated in CAM16 (to avoid dependence on Oklab uniformity), and restricted to colors inside the BT.2020 gamut (to avoid any wierd behavior for unrealistic or imaginary colors).

The same comparison is then repeated in Oklrab, Ottosson's revised version of Oklab which replaces the L axis with a "toe"-adjusted lightness estimate — intended to predict perceived lightness better under a strong adaptive white — while keeping the same a/b chroma axes. Applying the same unscaled and ×2-scaled distance formulas to Oklrab instead of Oklab gives two more metrics, named here ΔEOKr and ΔEOKr2 by analogy with ΔEOK / ΔEOK2. Oklrab is implemented in Color.js (as "oklrab"); ΔEOKr and ΔEOKr2 are computed in this repo (deltaEOKr / deltaEOKr2 in generate-colors.js) as Color.js has no built-in method for them.

Methodology

The full pipeline lives in run.js and is seeded, so the dataset (pairs.csv), regressions and plots reproduce exactly from node run.js.

Base colors

generateColors() draws N = 1000 base colors in CAM16-JMh, using Color.js for the color handling and gamut testing:

  • J (lightness) ~ Normal(μ = 60, σ = 20)
  • M (colorfulness) ~ Normal(μ = 25, σ = 20)
  • h (hue) ~ uniform over [0°, 360°)

A color is kept only if it is strictly inside the BT.2020 gamut; the generator resamples until exactly N are collected. Below, the kept colors are shown in the Oklab a–b plane, with the sRGB, P3 and BT.2020 gamut outlines (max-chroma silhouettes across all lightnesses) overlaid:

Base colors in Oklab a–b with gamut outlines

Because the reachable colorfulness depends on lightness and hue, gamut rejection skews the kept sample slightly: the kept means (J ≈ 57, M ≈ 23) sit a little below the input means. The dashed line marks the input mean.

Kept lightness (J) distribution Kept colorfulness (M) distribution

Color pairs

generatePairs() turns each base color into S = 5 similar colors by perturbing its coordinates independently, each ~ Normal(μ = base value, σ = 4), with hue wrapped to [0°, 360°). Again only similar colors inside BT.2020 are kept, resampling until each base has exactly S — giving N × S = 5000 [base, similar] pairs. This σ = 4 perturbation yields ΔE2000 differences spanning ~0–16 (mean ≈ 3.9), covering both the small differences of acceptability testing and the larger ones relevant to gamut mapping.

For every pair the five distances — ΔE2000, ΔEOK, ΔEOK2, ΔEOKr and ΔEOKr2 — are then computed, the first three with Color.js directly and the Oklrab-based ΔEOKr / ΔEOKr2 using Color.js's "oklrab" space.

Results

ΔE2000 is generally accepted as the best color-difference metric for SDR colors, but is computationally complex; ΔEOK, by contrast, is computationally simple. The question is how well the simpler metric (and its ΔEOK2 / ΔEOKr / ΔEOKr2 variants) can stand in for ΔE2000.

Taking ΔE2000 as the reference, each candidate metric is fit against it by ordinary least-squares linear regression. The higher the coefficient of determination (r²), the more of the ΔE2000 variation the metric explains — i.e. the better it agrees with ΔE2000.

Metric Best-fit line
ΔEOK ΔE2000 = 95.10·ΔEOK + 1.03 0.642
ΔEOK2 ΔE2000 = 85.37·ΔEOK2 + 0.47 0.722
ΔEOKr ΔE2000 = 81.79·ΔEOKr + 1.17 0.613
ΔEOKr2 ΔE2000 = 80.22·ΔEOKr2 + 0.45 0.732

ΔEOK vs ΔE2000 ΔEOK2 vs ΔE2000 ΔEOKr vs ΔE2000 ΔEOKr2 vs ΔE2000

ΔEOK2 tracks ΔE2000 more closely than ΔEOK (r² 0.722 vs 0.642): scaling the a and b axes by 2 measurably improves agreement with ΔE2000 on this dataset, supporting Ottosson's recommendation. The same pattern holds in Oklrab: ΔEOKr2 beats unscaled ΔEOKr (r² 0.732 vs 0.613), by a similar margin to the Oklab pair. Swapping in Oklrab's lightness doesn't change the picture much — ΔEOKr is slightly worse than ΔEOK, and ΔEOKr2 is slightly better than ΔEOK2 — consistent with Oklrab's lightness revision addressing adaptive-white viewing conditions that this dataset doesn't vary. Full per-pair figures are in regressions.json.

About

Examination of ΔE OK vs. OK2

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages