Implementacja CIEDE2000 w Lua

Wersja funkcji: v1.0.0
Statystyki strony
Liczba wizyt412
Liczba przeglądanych plików445 + 313

Ta strona prezentuje referencyjną implementację formuły różnicy kolorów CIEDE2000 w Lua. Jeśli chcesz uzyskać dokładne dopasowanie z implementacjami innych firm do 10 miejsc po przecinku, może być konieczne wprowadzenie pewnych zmian w kodzie źródłowym, w szczególności poprzez skomentowanie i odkomentowanie kilku wierszy, które można zastosować automatycznie za pomocą poniższego linku.

Schemat pełnej formuły CIEDE2000 ze składnikami L*a*b* i korektami

Funkcja ΔE2000 w Lua

Rozważmy bardziej powszechne i akademickie (Sharma, 2005) z dwóch sformułowań.

-- This function written in Lua is not affiliated with the CIE (International Commission on Illumination),
-- and is released into the public domain. It is provided "as is" without any warranty, express or implied.

-- The classic CIE ΔE2000 implementation, which operates on two L*a*b* colors, and returns their difference.
-- "l" ranges from 0 to 100, while "a" and "b" are unbounded and commonly clamped to the range of -128 to 127.
function ciede_2000(l_1, a_1, b_1, l_2, a_2, b_2)
	-- Working in Lua/LuaJIT with the CIEDE2000 color-difference formula.
	-- k_l, k_c, k_h are parametric factors to be adjusted according to
	-- different viewing parameters such as textures, backgrounds...
	local k_l, k_c, k_h = 1.0, 1.0, 1.0;
	local n = (math.sqrt(a_1 * a_1 + b_1 * b_1) + math.sqrt(a_2 * a_2 + b_2 * b_2)) * 0.5;
	n = n * n * n * n * n * n * n;
	-- A factor involving chroma raised to the power of 7 designed to make
	-- the influence of chroma on the total color difference more accurate.
	n = 1.0 + 0.5 * (1.0 - math.sqrt(n / (n + 6103515625.0)));
	-- Application of the chroma correction factor.
	local c_1 = math.sqrt(a_1 * a_1 * n * n + b_1 * b_1);
	local c_2 = math.sqrt(a_2 * a_2 * n * n + b_2 * b_2);
	-- atan2 is preferred over atan because it accurately computes the angle of
	-- a point (x, y) in all quadrants, handling the signs of both coordinates.
	local h_1 = math.atan2(b_1, a_1 * n);
	local h_2 = math.atan2(b_2, a_2 * n);
	if h_1 < 0.0 then h_1 = h_1 + 2.0 * math.pi end;
	if h_2 < 0.0 then h_2 = h_2 + 2.0 * math.pi end;
	n = math.abs(h_2 - h_1);
	-- Cross-implementation consistent rounding.
	if math.pi - 1E-14 < n and n < math.pi + 1E-14 then n = math.pi end;
	-- When the hue angles lie in different quadrants, the straightforward
	-- average can produce a mean that incorrectly suggests a hue angle in
	-- the wrong quadrant, the next lines handle this issue.
	local h_m = (h_1 + h_2) * 0.5;
	local h_d = (h_2 - h_1) * 0.5;
	if math.pi < n then
		h_d = h_d + math.pi;
		-- 📜 Sharma’s formulation doesn’t use the next line, but the one after it,
		-- and these two variants differ by ±0.0003 on the final color differences.
		h_m = h_m + math.pi;
		-- h_m = h_m + (h_m < math.pi and math.pi or -math.pi)
	end
	local p = 36.0 * h_m - 55.0 * math.pi;
	n = (c_1 + c_2) * 0.5;
	n = n * n * n * n * n * n * n;
	-- The hue rotation correction term is designed to account for the
	-- non-linear behavior of hue differences in the blue region.
	local r_t = -2.0 * math.sqrt(n / (n + 6103515625.0)) *
			math.sin(math.pi / 3.0 * math.exp(p * p / (-25.0 * math.pi * math.pi)));
	n = (l_1 + l_2) * 0.5;
	n = (n - 50.0) * (n - 50.0);
	-- Lightness.
	local l = (l_2 - l_1) / (k_l * (1.0 + 0.015 * n / math.sqrt(20.0 + n)));
	-- These coefficients adjust the impact of different harmonic
	-- components on the hue difference calculation.
	local t = 1.0	+ 0.24 * math.sin(2.0 * h_m + math.pi * 0.5)
			+ 0.32 * math.sin(3.0 * h_m + 8.0 * math.pi / 15.0)
			- 0.17 * math.sin(h_m + math.pi / 3.0)
			- 0.20 * math.sin(4.0 * h_m + 3.0 * math.pi / 20.0);
	n = c_1 + c_2;
	-- Hue.
	local h = 2.0 * math.sqrt(c_1 * c_2) * math.sin(h_d) / (k_h * (1.0 + 0.0075 * n * t));
	-- Chroma.
	local c = (c_2 - c_1) / (k_c * (1.0 + 0.0225 * n));
	-- Returning the square root ensures that dE00 accurately reflects the
	-- geometric distance in color space, which can range from 0 to around 185.
	return math.sqrt(l * l + h * h + c * c + c * h * r_t);
end

-- GitHub Project : https://github.com/michel-leonard/ciede2000-color-matching
--   Online Tests : https://michel-leonard.github.io/ciede2000-color-matching

-- L1 = 42.5   a1 = 23.6   b1 = -4.4
-- L2 = 45.2   a2 = 18.5   b2 = 3.5
-- CIE ΔE00 = 6.4300403439 (Bruce Lindbloom, Netflix’s VMAF, ...)
-- CIE ΔE00 = 6.4300224381 (Gaurav Sharma, OpenJDK, ...)
-- Deviation between implementations ≈ 1.8e-5

-- See the source code comments for easy switching between these two widely used ΔE*00 implementation variants.

Dokładność i niezawodność kodu źródłowego

Różnica między formułami Sharmy i Lindbloom nigdy nie przekracza ±0,0003 w końcowym ΔE2000, co odpowiada zwykłej różnicy mierzonej między dwiema implementacjami 32-bitowymi i jest niezauważalna dla ludzkiego oka. Nasze implementacje 64-bitowe, wszystkie spójne ze sobą, gwarantują co najmniej 10 poprawnych miejsc dziesiętnych, więc wybór jednej formuły zamiast drugiej zależy głównie od wymaganej interoperacyjności. Kod źródłowy, który pojawia się domyślnie na tej stronie, odpowiada najczęściej używanemu wariantowi (jego zaletą jest baza społeczności i większa prostota, gdy w grę wchodzi wektoryzacja).

Jeśli znajdziesz komentarz w kodzie źródłowym, który nie odpowiada innemu językowi, poinformuj o tym autora strony, który przeanalizuje Twoją sugestię i włączy ją do kodu źródłowego.

Jak przekonwertować kolory RGB na L*a*b*?

Do konwersji należy użyć pośredniej przestrzeni kolorów XYZ, a jeśli potrzebujesz pomocy, kod źródłowy znajduje się na dole tej strony (przy użyciu punktu bieli D65 sformalizowanego w 1964 r.).

Zakresy wartości w CIELAB i interpretacja ΔE2000

W przestrzeni barw CIELAB składnik L* oznacza jasność i zwykle mieści się w zakresie od 0 (czarny) do 100 (biały). Składniki a* i b* opisują osie barw: a* przechodzi od zielonego do czerwonego, a b* od niebieskiego do żółtego. W praktyce wartości a* i b* mieszczą się najczęściej w przedziale od -128 do +127, choć mogą nieznacznie go przekraczać w zależności od konwersji kolorów.

Przykład dwóch kolorów prezentujących zauważalną różnicę (JND) według CIEDE2000
Kolor 1Kolor 2Wartość ΔE2000
1
2
3
Przykłady wartości CIEDE2000 obliczonych dla dwóch kolorów różnych
Kolor 1Kolor 2Wartość ΔE2000
5
10
15

Parametry k_l, k_c i k_h

Parametry k_l, k_c i k_h to czynniki wagowe stosowane odpowiednio do składników jasności (ΔL*), chromy (ΔC*) i barwy (ΔH*) w formule CIEDE2000. Ich wartość domyślna to 1, co odpowiada standardowym warunkom obserwacji zalecanym przez Międzynarodową Komisją Oświetleniową. W praktyce współczynniki te są dostosowywane do specyficznych warunków: na przykład k_l = 2 bywa stosowane, aby nadać większą wagę różnicom jasności (częste w druku), podczas gdy k_c lub k_h mogą być zmniejszane, aby zwiększyć tolerancję na różnice w nasyceniu lub barwie w zależności od wymagań kontroli jakości. W zależności od kontekstu współczynniki te zwykle mieszczą się w zakresie od 0,5 do 2.

ΔE2000 (CIEDE2000) określa percepcyjną różnicę między dwoma kolorami: 0 oznacza identyczne kolory, a wyższe wartości (do około 185 w skrajnych przypadkach) wskazują na większą różnicę. Na przykład wartość ΔE2000 około 5 oznacza kolory podobne, natomiast około 15 oznacza kolory wyraźnie różne.

Przykład zastosowania w Lua

-- Compute the Delta E (CIEDE2000) color difference between two L*a*b* colors in Lua

-- Color 1
local L1, a1, b1 = 75.1, 61.9, -3.2

-- Color 2
local L2, a2, b2 = 75.6, 55.9, 3.1

local deltaE = ciede_2000(L1, a1, b1, L2, a2, b2)
print(deltaE)

-- .................................................. This shows a ΔE2000 of 3.3591979531
-- As explained in the comments, compliance with Gaurav Sharma would display 3.3591841825

Wyniki testów

Sterownik napisany w języku C99, z 250 dokładnymi testami statycznymi, udowodnił, że ta funkcja Lua jest interoperacyjna z funkcją CIEDE2000 dostępną w innych językach programowania.

CIEDE2000 Verification Summary :
  First Verified Line : 25.3,0.28,53.78,65.8,-101.21,-86,67.92949263023695
             Duration : 19.28 s
            Successes : 10000000
               Errors : 0
      Average Delta E : 62.9474
    Average Deviation : 4.2586916049192067e-15
    Maximum Deviation : 1.1368683772161603e-13

Pliki do pobrania

Zachęcamy do korzystania z tych plików udostępnionych przez Michela, nawet w celach komercyjnych.

Statystyki strony : pobieranie plików
PlikRozmiarLiczba kliknięć
ciede-2000.lua4 KB83
ciede-2000-driver.lua5 KB63
ciede-2000-random.lua5 KB68
compare-rgb-hex-colors.lua9 KB64
stdin-verifier.lua6 KB69
test-lua.yml3 KB50
vs-tiny-devicons.yml5 KB48
reference-dataset.txt4 KB313
Kliknij lua.zip, aby pobrać wszystkie pliki w archiwum.

Społeczność

Jeśli chciałbyś zostawić swoją opinię na temat tego kodu źródłowego Lua lub ogólnie na temat CIEDE2000, księga gości zawiera już 1 wiadomości w języku polskim i 9 wiadomości ogółem, więc daj nam znać, co myślisz.