Implementazione di CIEDE2000 in Perl

Versione della funzione: v1.0.0
Statistiche del sito
Numero di visite461
Numero di file visualizzati282 + 376

Questa pagina presenta un’implementazione di riferimento della formula della differenza di colore CIEDE2000 in Perl. Se si vuole garantire la perfetta compatibilità (con la decima cifra decimale) con alcune implementazioni di terze parti, potrebbe essere necessario modificare i commenti nel codice sorgente. Per facilitare questa operazione, il seguente link la automatizza.

Diagramma della formula CIEDE2000 in forma completa con i componenti L*a*b* e le regolazioni

La funzione ΔE2000 in Perl

Consideriamo la più comune e accademica (Sharma, 2005) delle due formulazioni.

# This function written in Perl 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.

use strict;
use warnings;
use Math::Trig qw(pi);

# 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.
sub ciede_2000 {
	# Working in Perl 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...
	my ($l_1, $a_1, $b_1, $l_2, $a_2, $b_2) = @_;
	my ($k_l, $k_c, $k_h) = (1.0, 1.0, 1.0);
	my $n = (sqrt($a_1 * $a_1 + $b_1 * $b_1) + 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 - sqrt($n / ($n + 6103515625.0)));
	# Application of the chroma correction factor.
	my $c_1 = sqrt($a_1 * $a_1 * $n * $n + $b_1 * $b_1);
	my $c_2 = 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.
	my $h_1 = atan2($b_1, $a_1 * $n);
	my $h_2 = atan2($b_2, $a_2 * $n);
	$h_1 += 2.0 * pi if $h_1 < 0.0;
	$h_2 += 2.0 * pi if $h_2 < 0.0;
	$n = abs($h_2 - $h_1);
	# Cross-implementation consistent rounding.
	$n = pi if pi - 1E-14 < $n && $n < pi + 1E-14;
	# 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.
	my $h_m = ($h_1 + $h_2) * 0.5;
	my $h_d = ($h_2 - $h_1) * 0.5;
	if (pi < $n) {
		$h_d += 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 += pi;
		# $h_m += ($h_m < pi) ? pi : -pi;
	}
	my $p = 36.0 * $h_m - 55.0 * 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.
	my $r_t = -2.0 * sqrt($n / ($n + 6103515625.0))
			* sin(pi / 3.0 * exp($p * $p / (-25.0 * pi * pi)));
	$n = ($l_1 + $l_2) * 0.5;
	$n = ($n - 50.0) * ($n - 50.0);
	# Lightness.
	my $l = ($l_2 - $l_1) / ($k_l * (1.0 + 0.015 * $n / sqrt(20.0 + $n)));
	# These coefficients adjust the impact of different harmonic
	# components on the hue difference calculation.
	my $t = 1.0	+ 0.24 * sin(2.0 * $h_m + pi * 0.5)
			+ 0.32 * sin(3.0 * $h_m + 8.0 * pi / 15.0)
			- 0.17 * sin($h_m + pi / 3.0)
			- 0.20 * sin(4.0 * $h_m + 3.0 * pi / 20.0);
	$n = $c_1 + $c_2;
	# Hue.
	my $h = 2.0 * sqrt($c_1 * $c_2) * sin($h_d) / ($k_h * (1.0 + 0.0075 * $n * $t));
	# Chroma.
	my $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 sqrt($l * $l + $h * $h + $c * $c + $c * $h * $r_t);
}

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

# L1 = 30.3   a1 = 46.0   b1 = 3.4
# L2 = 31.0   a2 = 40.9   b2 = -2.7
# CIE ΔE00 = 3.7301344547 (Bruce Lindbloom, Netflix’s VMAF, ...)
# CIE ΔE00 = 3.7301485713 (Gaurav Sharma, OpenJDK, ...)
# Deviation between implementations ≈ 1.4e-5

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

Parametri k_l, k_c e k_h

I parametri k_l, k_c e k_h nella formula CIEDE2000 sono fattori di ponderazione applicati rispettivamente alle componenti di luminosità (ΔL*), croma (ΔC*) e tinta (ΔH*). Sono definiti come costanti nel codice sorgente. Nel codice sorgente sono definiti come costanti con un valore predefinito di 1, che corrisponde alle condizioni di osservazione standard stabilite dalla Commissione internazionale per l’illuminazione (CIE). In pratica, potrebbe essere necessario regolare questi coefficienti per riflettere condizioni specifiche: ad esempio, k_l = 2 viene talvolta utilizzato per dare maggior peso alle differenze di luminosità (un caso comune nell’industria tessile), mentre k_c o k_h possono essere ridotti per aumentare la tolleranza alle variazioni di saturazione o di tonalità, a seconda delle esigenze. A seconda del contesto, questi coefficienti variano in genere da 0,5 a 2.

Precisione e affidabilità del codice sorgente

La differenza tra la formulazione accademica di Sharma e quella semplificata di Lindbloom non supera ±0,0003 sul ΔE2000 finale. Ciò corrisponde alla differenza solitamente misurata tra due implementazioni a 32 bit ed è impercettibile all’occhio umano. Le nostre implementazioni a 64 bit, tutte coerenti tra loro, garantiscono almeno 10 cifre decimali corrette, quindi la scelta di una formulazione rispetto all’altra è un dettaglio tecnico. La formula predefinita in questa pagina è quella presentata più spesso nella comunità, è leggermente più facile da vettorializzare.

Se notate che i commenti nel codice sorgente non corrispondono ai commenti in inglese, siete pregati di informare l’autore della pagina in modo da poterli correggere.

Come si convertono i colori RGB in L*a*b*?

Andate alla pagina AWK, C, Dart, Java, JavaScript, Kotlin, Lua, PHP, Python, Ruby o Rust dove tale convertitore (che utilizza l’illuminante D65) è già implementato in aggiunta alla funzione di confronto dei colori.

Intervalli di valori in CIELAB e interpretazione del ΔE2000

Nello spazio colore CIELAB, la componente L* rappresenta la luminosità e varia tipicamente da 0 (nero) a 100 (bianco). Le componenti a* e b* definiscono gli assi cromatici: a* va dal verde al rosso, mentre b* va dal blu al giallo. In pratica, i valori di a* e b* si collocano solitamente tra -128 e +127, anche se possono superare leggermente questi limiti in base alle conversioni cromatiche.

Esempio di due colori che presentano una differenza appena percettibile (JND) secondo CIEDE2000
Colore 1Colore 2Valore di ΔE2000
1
2
3
Esempi di valori CIEDE2000 calcolati tra due colori diversi
Colore 1Colore 2Valore di ΔE2000
5
10
15

ΔE2000 (CIEDE2000) misura la differenza percepita tra due colori: 0 significa colori identici, e valori più alti (fino a circa 185 nei casi estremi) indicano una differenza più evidente. Per esempio, un ΔE2000 intorno a 5 indica colori vicini, mentre intorno a 15 indica colori chiaramente distinti.

Esempio di utilizzo in Perl

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

# Color 1: L1 = 97.9   a1 = 28.2   b1 = 3.0
# Color 2: L2 = 98.4   a2 = 22.0   b2 = -2.1

my $deltaE = ciede_2000($L1, $a1, $b1, $L2, $a2, $b2);
print $deltaE;

# .................................................. This shows a ΔE2000 of 4.4744286885
# As explained in the comments, compliance with Gaurav Sharma would display 4.4744462960

I risultati dei test

Il driver scritto in linguaggio C99, con 250 test statici precisi, ha dimostrato che questa funzione Perl è interoperabile con la funzione CIEDE2000 disponibile in altri linguaggi di programmazione.

CIEDE2000 Verification Summary :
  First Verified Line : 2,-126.1,-93.21,61.07,-94.6,65.5,70.390530131414
             Duration : 59.14 s
            Successes : 10000000
               Errors : 0
      Average Delta E : 62.9418
    Average Deviation : 4.5890806760207067e-14
    Maximum Deviation : 5.6843418860808015e-13

File da scaricare

Sentitevi liberi di utilizzare questi file messi a disposizione da Michel, anche per scopi commerciali.

Statistiche del sito : download di file
FileDimensioneNumero di clic
ciede-2000.pl4 KB80
ciede-2000-driver.pl5 KB87
ciede-2000-random.pl5 KB77
test-pl.yml3 KB38
reference-dataset.txt4 KB376
Fai clic su pl.zip per scaricare tutti i file in un archivio.

Comunità

Cosa ne pensate di questo codice sorgente o di CIEDE2000? La vostra opinione è importante per noi! Il libro degli ospiti contiene già 9 messaggi, di cui 1 in italiano. Date un’occhiata e condividete la vostra opinione.