Implementación de CIEDE2000 en bc

Versión de la función: v1.0.0
Estadísticas del sitio
Número de visitas807
Número de archivos consultados318 + 606

Esta página presenta una implementación de referencia de la fórmula de diferencia de color CIEDE2000 escrita en el lenguaje de programación bc. Si desea garantizar una compatibilidad perfecta (hasta el décimo decimal) con algunas implementaciones de terceros, es posible que tenga que modificar los comentarios del código fuente. Para facilitarlo, el siguiente enlace automatiza esta operación.

Diagrama de la fórmula CIEDE2000 completa con los componentes L*a*b* y los ajustes.

La función ΔE2000 en bc

Consideremos la más común y académica (Sharma, 2005) de las dos formulaciones.

/* Esta función escrita en bc es de dominio público y no
está afiliada a la CIE (Comisión Internacional de Iluminación). */

m_pi = 0.0

/* La implementación clásica de CIEDE2000 que recibe dos colores L*a*b* y devuelve su diferencia.
El componente "L" varía de 0 a 100. "a" y "b" normalmente se proyectan entre -128 y 127. */
define ciede_2000(l_1, a_1, b_1, l_2, a_2, b_2) {
	/* Ejecuta el cálculo de diferencia de color CIEDE2000 en Basic Calculator.
	k_l, k_c y k_h son factores paramétricos a ajustar según
	sus necesidades de visualización (texturas, fondos). */
	k_l = 1.0
	k_c = 1.0
	k_h = 1.0
	if (m_pi == 0.0) {
		/* Cálculo de π … 3,141592653589793238462643383279502884197169399375105820974945
		con una precisión arbitraria utilizando la fórmula de Machin propuesta en 1706. */
		m_pi =  16.0 * a(0.2) - 4.0 * a(1.0 / 239.0)
	}
	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
	/* Un factor que implica la croma elevada a la potencia 7,
	diseñado para tener más en cuenta la influencia de la croma. */
	n = 1.0 + 0.5 * (1.0 - sqrt(n / (n + 6103515625.0)))
	/* Aplicación del factor de corrección de la croma para compensar su no linealidad. */
	c_1 = sqrt(a_1 * a_1 * n * n + b_1 * b_1)
	c_2 = sqrt(a_2 * a_2 * n * n + b_2 * b_2)
	/* Uso de 14 líneas para simular atan2, ya que bc no dispone de esta función de forma nativa. */
	if (0.0 < a_1) {
		h_1 = a(b_1 / (a_1 * n)) + (b_1 < 0.0) * 2.0 * m_pi
	} else if (a_1 < 0.0) {
		h_1 = a(b_1 / (a_1 * n)) + m_pi
	} else {
		h_1 = m_pi + ((b_1 < 0.0) - (0.0 < b_1)) * 0.5 * m_pi
	}
	if (0.0 < a_2) {
		h_2 = a(b_2 / (a_2 * n)) + (b_2 < 0.0) * 2.0 * m_pi
	} else if (a_2 < 0.0) {
		h_2 = a(b_2 / (a_2 * n)) + m_pi
	} else {
		h_2 = m_pi + ((b_2 < 0.0) - (0.0 < b_2)) * 0.5 * m_pi
	}
	/* El polyfill atan2 (personalizado) está terminado. */
	if (h_2 < h_1) { n = h_1 - h_2; } else { n = h_2 - h_1; }
	/* Evita que la rama dependa del RoundingMode del lenguaje de programación. */
	if (m_pi - 0.00000000000001 < n && n < m_pi + 0.00000000000001) { n = m_pi; }
	/* Cuando los ángulos de tono se encuentran en diferentes cuadrantes,
	la media aritmética simple puede dar un ángulo incorrecto, las
	líneas siguientes aplican la corrección angular necesaria. */
	h_m = (h_1 + h_2) * 0.5
	h_d = (h_2 - h_1) * 0.5
	if (m_pi < n) {
		h_d = h_d + m_pi
		/* 📜 La formulación de Sharma no utiliza la línea siguiente, sino la que le sigue.
		Nota: estas dos variantes sólo difieren en ±0,0003 en la diferencia de color final. */
		h_m = h_m + m_pi
		/* h_m = h_m + ((h_m < m_pi) - (m_pi <= h_m)) * m_pi */
	}
	p = 36.0 * h_m - 55.0 * m_pi
	n = (c_1 + c_2) * 0.5
	n = n * n * n * n * n * n * n
	/* El término de corrección de la rotación del tono mejora la precisión
	del algoritmo, especialmente cuando la comparación se refiere a azules. */
	r_t = -2.0 * sqrt(n / (n + 6103515625.0)) \
			* s(m_pi / 3.0 * e(p * p / (-25.0 * m_pi * m_pi)))
	n = (l_1 + l_2) * 0.5
	n = (n - 50.0) * (n - 50.0)
	/*  Luminosidad . */
	l = (l_2 - l_1) / (k_l * (1.0 + 0.015 * n / sqrt(20.0 + n)))
	/* Estos coeficientes se utilizan para modular la influencia de
	los componentes armónicos en el cálculo de la diferencia de tono. */
	t = 1.0 	+ 0.24 * s(2.0 * h_m + m_pi / 2.0) \
			+ 0.32 * s(3.0 * h_m + 8.0 * m_pi / 15.0) \
			- 0.17 * s(h_m + m_pi / 3.0) \
			- 0.20 * s(4.0 * h_m + 3.0 * m_pi / 20.0)
	n = c_1 + c_2
	/* Tono. */
	h = 2.0 * sqrt(c_1 * c_2) * s(h_d) / (k_h * (1.0 + 0.0075 * n * t))
	/* Croma. */
	c = (c_2 - c_1) / (k_c * (1.0 + 0.0225 * n))
	/* Devolver la raíz cuadrada garantiza que dE00 representa una distancia
	geométrica (que va de 0 a aproximadamente 185) en el espacio CIELAB. */
	return sqrt(l * l + h * h + c * c + c * h * r_t)
}

/*
     Proyecto GitHub : https://github.com/michel-leonard/ciede2000-color-matching
    Pruebas en línea : https://michel-leonard.github.io/ciede2000-color-matching

   L1 = 30.8   a1 = 22.0   b1 = -4.4
   L2 = 28.1   a2 = 16.4   b2 = 4.3
   CIE ΔE00 = 7.0779305175 (Bruce Lindbloom, Netflix’s VMAF, ...)
   CIE ΔE00 = 7.0779164917 (Gaurav Sharma, OpenJDK, ...)
   Desviación entre implementaciones ≈ 1.4e-5

   Consulte los comentarios del código fuente para pasar de una de estas variantes de implementación ΔE*00 a la otra.
*/

Parámetros k_l, k_c y k_h

Los parámetros k_l, k_c y k_h de la fórmula CIEDE2000 son factores de ponderación que se aplican a los componentes de luminosidad (ΔL*), croma (ΔC*) y tono (ΔH*), respectivamente. En el código fuente, se definen como constantes cuyo valor por defecto es 1, lo que se corresponde con las condiciones de observación estándar establecidas por la Comisión Internacional de Iluminación (CIE). En la práctica, puede ser necesario ajustar estos coeficientes para reflejar condiciones específicas: por ejemplo, k_l = 2 se utiliza a veces para dar más peso a las diferencias de brillo (algo habitual en la industria textil), mientras que k_c o k_h pueden reducirse para aumentar la tolerancia a las variaciones de saturación o tono. En resumen, estos coeficientes suelen oscilar entre 0,5 y 2, siendo 1 el valor más habitual.

Precisión y fiabilidad del código fuente

La diferencia entre la formulación académica de Sharma y la simplificada de Lindbloom no supera ±0,0003 en el ΔE2000 final. La implementación que aquí se presenta es de 64 bits y garantiza una precisión de más de 10 decimales; por lo tanto, la elección de una formulación en lugar de otra es un detalle técnico. En la parte superior de esta página, puedes elegir entre las dos formulaciones; la que se muestra actualmente es la formulación simplificada.

¿Cómo determinar si una implementación determinada de CIEDE2000 es académica o simplificada?

¿Cómo se convierten los colores RGB a L*a*b*?

Vaya a la página AWK, C, Dart, Java, JavaScript, Kotlin, Lua, PHP, Python, Ruby o Rust, donde ya está implementado dicho conversor (que utiliza el iluminante D65), además de la función de comparación de colores.

Rangos de valores en CIELAB e interpretación del ΔE2000

En el espacio de color CIELAB, el componente L* representa la luminosidad y suele variar de 0 (negro) a 100 (blanco). Los componentes a* y b* definen los ejes de color: a* va del verde al rojo, y b* del azul al amarillo. En la práctica, los valores de a* y b* casi siempre se limitan a un intervalo comprendido entre -128 y +127, aunque la norma no establece un límite oficial para estos dos componentes.

Ejemplo de dos colores que presentan una diferencia apenas perceptible (JND) según CIEDE2000
Color 1Color 2Valor de ΔE2000
1
2
3
Ejemplos de valores CIEDE2000 calculados entre dos colores distintos
Color 1Color 2Valor de ΔE2000
5
10
15

ΔE2000 (CIEDE2000) cuantifica la diferencia perceptible entre dos colores: 0 significa que son idénticos, y valores más altos (hasta 185 y más) indican una diferencia más notable. Por ejemplo, un ΔE2000 alrededor de 5 indica colores cercanos, mientras que alrededor de 15 indica colores claramente distintos. Cuando el valor ΔE2000 supera 40, los colores comparados ya casi no tienen nada en común, y no podemos extraer de ellos información precisa.

Ejemplo de uso en bc

echo 'scale=50;ciede_2000(13.1, 11.9, 3.8, 13.0, 17.6, -4.9)' | bc -l ciede-2000.bc

# Outputs: 7.37458016458016885544127036110301868134320454640263
# As explained in the comments, compliance with Gaurav Sharma would display ...
# ........ 7.37456659946646273510289154231355556542867583609039

Los resultados de las pruebas

Esta función bc se ha probado con el controlador Julia de precisión múltiple diseñado para este fin. Estas pruebas garantizan que tus cálculos se realizarán sin errores, incluso en casos límite críticos, por ejemplo, cuando la función arcotangente devuelve un valor matemáticamente indefinido.

CIEDE2000 Verification Summary :
  First Verified Line : 27,-123,101,44,42.0000098,-99,70.204734814936909810694644954670527048474482887
             Duration : 18644.34 s
            Successes : 10000000
               Errors : 0
      Average Delta E : 62.9618
    Average Deviation : 4.0e-38
    Maximum Deviation : 2.2e-35

Archivos para descargar

A continuación encontrará un archivo que permite realizar cálculos de precisión arbitraria en bc (útil si trabaja con ΔE2000 en metrología). Siéntase libre de utilizar estos archivos puestos a disposición por Michel, incluso con fines comerciales.

Estadísticas del sitio : descargas de archivos
ArchivoTamañoNúmero de clics
ciede-2000.bc4 KB143
test-bc-arbitrary.yml7 KB100
test-bc-standard.yml5 KB75
reference-dataset.txt4 KB606
Haga clic en bc.zip para descargar todos estos archivos en un archivo.

Comunidad

¿Qué opina de este código fuente o de CIEDE2000? Su opinión es importante para nosotros. El libro de visitas ya contiene 9 mensajes - incluyendo 1 en español. Eche un vistazo y comparta su opinión.