Implementación de CIEDE2000 en Rust
| Número de visitas | 632 |
|---|---|
| Número de archivos consultados | 713 + 390 |
Esta página presenta una implementación de referencia de la fórmula de diferencia de color CIEDE2000 en Rust. 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.
La función ΔE2000 en Rust
Consideremos la más común y académica (Sharma, 2005) de las dos formulaciones.
// Esta función escrita en Rust es de dominio público y no
// está afiliada a la CIE (Comisión Internacional de Iluminación).
// 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.
fn ciede_2000(l_1: f64, a_1: f64, b_1: f64, l_2: f64, a_2: f64, b_2: f64) -> f64 {
// Ejecuta el cálculo de diferencia de color CIEDE2000 en Rust.
// K_L, K_C y K_H son factores paramétricos a ajustar según
// sus necesidades de visualización (texturas, fondos).
const K_L: f64 = 1.0;
const K_C: f64 = 1.0;
const K_H: f64 = 1.0;
const M_PI: f64 = std::f64::consts::PI;
let mut n = ((a_1 * a_1 + b_1 * b_1).sqrt() + (a_2 * a_2 + b_2 * b_2).sqrt()) * 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 - (n / (n + 6103515625.0)).sqrt());
// Aplicación del factor de corrección de la croma para compensar su no linealidad.
let c_1: f64 = (a_1 * a_1 * n * n + b_1 * b_1).sqrt();
let c_2: f64 = (a_2 * a_2 * n * n + b_2 * b_2).sqrt();
// La función atan2 es preferible a atan porque calcula el ángulo de un
// punto (x, y) en todos los cuadrantes, teniendo en cuenta el signo de x e y.
let mut h_1 = b_1.atan2(a_1 * n);
let mut h_2 = b_2.atan2(a_2 * n);
if h_1 < 0.0 { h_1 += 2.0 * M_PI; }
if h_2 < 0.0 { h_2 += 2.0 * M_PI; }
n = (h_2 - h_1).abs();
// Evita que la rama dependa del RoundingMode del lenguaje de programación.
if (M_PI - 1e-14..=M_PI + 1e-14).contains(&n) { 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.
let mut h_m = (h_1 + h_2) * 0.5;
let mut h_d = (h_2 - h_1) * 0.5;
if M_PI < n {
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 += M_PI;
// if h_m < M_PI { h_m += M_PI; } else { h_m -= M_PI; }
}
let 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.
let r_t = -2.0 * (n / (n + 6103515625.0)).sqrt() * (M_PI / 3.0 * (p * p / (-25.0 * M_PI * M_PI)).exp()).sin();
n = (l_1 + l_2) * 0.5;
n = (n - 50.0) * (n - 50.0);
// Luminosidad .
let l = (l_2 - l_1) / (K_L * (1.0 + 0.015 * n / (20.0 + n).sqrt()));
// Estos coeficientes se utilizan para modular la influencia de
// los componentes armónicos en el cálculo de la diferencia de tono.
let t = 1.0 + 0.24 * (2.0 * h_m + M_PI * 0.5).sin()
+ 0.32 * (3.0 * h_m + 8.0 * M_PI / 15.0).sin()
- 0.17 * (h_m + M_PI / 3.0).sin()
- 0.20 * (4.0 * h_m + 3.0 * M_PI / 20.0).sin();
n = c_1 + c_2;
// Tono.
let h = 2.0 * (c_1 * c_2).sqrt() * (h_d).sin() / (K_H * (1.0 + 0.0075 * n * t));
// Croma.
let 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.
(l * l + h * h + c * c + c * h * r_t).sqrt()
}
// Proyecto GitHub : https://github.com/michel-leonard/ciede2000-color-matching
// Pruebas en línea : https://michel-leonard.github.io/ciede2000-color-matching
// L1 = 93.1 a1 = 39.1 b1 = -1.8
// L2 = 93.6 a2 = 33.8 b2 = 1.8
// CIE ΔE00 = 2.9146136126 (Bruce Lindbloom, Netflix’s VMAF, ...)
// CIE ΔE00 = 2.9146004027 (Gaurav Sharma, OpenJDK, ...)
// Desviación entre implementaciones ≈ 1.3e-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. Esto corresponde a la diferencia que suele medirse entre dos implementaciones de 32 bits y es imperceptible para el ojo humano. La implementación que se presenta en esta página es de 64 bits y garantiza al menos 10 decimales correctos; por lo tanto, la elección de una formulación en lugar de otra es un detalle técnico. La fórmula por defecto de esta página es la que se presenta con más frecuencia en la comunidad, es ligeramente más fácil de vectorizar.
¿Cómo se determina si una implementación es de tipo académico o simplificado?
- Evalúa
ciede_2000(27.5, 24.6, 9.2, 15.7, 56.6, -18.5) - si el resultado es
19.999944, la implementación es de tipo académico - si el resultado es
20.000002, la implementación es de tipo simplificado
¿Cómo se convierten los colores RGB a L*a*b*?
Deberá utilizar el espacio de color intermedio XYZ para la conversión y, si necesita ayuda, al final de esta página encontrará el código fuente (que utiliza el punto blanco D65 formalizado en 1964).
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.
| Color 1 | Color 2 | Valor de ΔE2000 |
|---|---|---|
| 1 | ||
| 2 | ||
| 3 |
| Color 1 | Color 2 | Valor 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 Rust
// Compute the Delta E (CIEDE2000) color difference between two L*a*b* colors in Rust
let (l1, a1, b1) = (22.4, 48.8, -3.7);
let (l2, a2, b2) = (23.2, 42.8, 4.0);
let delta_e = ciede_2000(l1, a1, b1, l2, a2, b2);
println!("ΔE2000: {}", delta_e);
// .................................................. This shows a ΔE2000 of 4.5321090902
// As explained in the comments, compliance with Gaurav Sharma would display 4.5320940436Los resultados de las pruebas
Nuestro programa de pruebas, escrito en C99, incluye 250 pruebas estáticas precisas. Los resultados muestran que esta función de CIEDE2000 en Rust es interoperable con los otros 41 lenguajes de programación.
CIEDE2000 Verification Summary :
First Verified Line : 24,122.6,117,21,-40.999999999847,-46,81.76266354804146
Duration : 14.79 s
Successes : 10000000
Errors : 0
Average Delta E : 63.2338
Average Deviation : 4.6e-15
Maximum Deviation : 1.1e-13Archivos para descargar
Siéntase libre de utilizar estos archivos puestos a disposición por Michel, incluso con fines comerciales.
| Archivo | Tamaño | Número de clics |
|---|---|---|
| ciede-2000.rs | 4 KB | 101 |
| ciede-2000-driver.rs | 5 KB | 96 |
| ciede-2000-generic.rs | 6 KB | 100 |
| ciede-2000-random.rs | 6 KB | 97 |
| compare-hex-colors.rs | 10 KB | 99 |
| compare-rgb-colors.rs | 9 KB | 98 |
| test-rs.yml | 3 KB | 59 |
| vs-palette.yml | 5 KB | 63 |
| reference-dataset.txt | 4 KB | 390 |
| Haga clic en rs.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.