Estoy buscando algún tipo de fórmula o algoritmo para determinar el brillo de un color dados los valores RGB. Sé que no puede ser tan simple como sumar los valores RGB y que las sumas más altas sean más brillantes, pero no sé por dónde empezar.
387
Respuestas:
¿Te refieres al brillo? Brillo percibido? Luminancia?
(0.2126*R + 0.7152*G + 0.0722*B)
[1](0.299*R + 0.587*G + 0.114*B)
[2]→sqrt( 0.241*R^2 + 0.691*G^2 + 0.068*B^2 )
sqrt( 0.299*R^2 + 0.587*G^2 + 0.114*B^2 )
(gracias a @MatthewHerbst ) [3]fuente
0.299*(R^2)
(porque la exponenciación va antes de la multiplicación)Creo que lo que estás buscando es la fórmula de conversión RGB -> Luma .
Fotométrico / digital ITU BT.709 :
Digital ITU BT.601 (da más peso a los componentes R y B):
Si está dispuesto a cambiar la precisión por el rendimiento, hay dos fórmulas de aproximación para esta:
Estos se pueden calcular rápidamente como
fuente
Blue
+ 3 * Verde) / 6, la segunda es (3 * Rojo +Blue
+ 4 * Verde) >> 3. concedido, en ambas aproximaciones rápidas, el azul tiene el peso más bajo, pero sigue ahí.Y = (R<<1+R+G<<2+B)>>3
(eso es solo 3-4 ciclos de CPU en ARM) pero supongo que un buen compilador hará esa optimización por usted.He hecho una comparación de los tres algoritmos en la respuesta aceptada. Generé colores en un ciclo donde solo se usaba cada 400 colores. Cada color está representado por 2x2 píxeles, los colores se ordenan del más oscuro al más claro (de izquierda a derecha, de arriba a abajo).
Primera imagen - Luminancia (relativa)
Segunda imagen: http://www.w3.org/TR/AERT#color-contrast
3a imagen - Modelo de color HSP
4a imagen: WCAG 2.0 SC 1.4.3 fórmula relativa de luminancia y relación de contraste (consulte la respuesta de @ Synchro aquí )
El patrón a veces se puede ver en la primera y segunda imagen según la cantidad de colores en una fila. Nunca vi ningún patrón en la imagen del tercer o cuarto algoritmo.
Si tuviera que elegir, usaría el algoritmo número 3, ya que es mucho más fácil de implementar y es aproximadamente un 33% más rápido que el 4to.
fuente
^2
esqrt
incluidos en la tercera fórmula son una forma más rápida de aproximar RGB lineal de RGB no lineal en lugar de^2.2
y^(1/2.2)
eso sería más correcto. Desafortunadamente, el uso de entradas no lineales en lugar de lineales es extremadamente común.A continuación se muestra el único algoritmo CORRECTO para convertir imágenes sRGB, como se usa en navegadores, etc., en escala de grises.
Es necesario aplicar un inverso de la función gamma para el espacio de color antes de calcular el producto interno. Luego aplica la función gamma al valor reducido. Si no se incorpora la función gamma, pueden producirse errores de hasta el 20%.
Para material informático típico, el espacio de color es sRGB. Los números correctos para sRGB son aprox. 0.21, 0.72, 0.07. Gamma para sRGB es una función compuesta que se aproxima a la exponenciación en 1 / (2.2). Aquí está todo en C ++.
fuente
La respuesta "aceptada" es incorrecta e incompleta
Las únicas respuestas que son precisas son las respuestas @ jive-dadson y @EddingtonsMonkey , y en soporte @ nils-pipenbrinck . Las otras respuestas (incluidas las aceptadas) se vinculan o citan fuentes que son incorrectas, irrelevantes, obsoletas o rotas.
Brevemente:
Lo que sigue es una respuesta correcta y completa:
Debido a que este hilo aparece altamente en los motores de búsqueda, estoy agregando esta respuesta para aclarar los diversos conceptos erróneos sobre el tema.
El brillo es un atributo perceptual, no tiene una medida directa.
La ligereza percibida se mide mediante algunos modelos de visión como CIELAB, aquí L * (Lstar) es una medida de la ligereza perceptiva y no es lineal para aproximar la curva de respuesta no lineal de la visión humana.
La luminancia es una medida lineal de la luz, espectralmente ponderada para la visión normal pero no ajustada para la percepción no lineal de la luminosidad.
Luma ( Y ' prime) es una señal ponderada codificada en gamma utilizada en algunas codificaciones de video. No debe confundirse con la luminancia lineal.
La curva de transferencia o gamma (TRC) es una curva que a menudo es similar a la curva perceptiva, y se aplica comúnmente a los datos de imagen para almacenamiento o transmisión para reducir el ruido percibido y / o mejorar la utilización de datos (y razones relacionadas).
Para determinar la luminosidad percibida , primero convierta los valores de imagen R´G´B´ codificados con gamma en luminancia lineal (
L
oY
) y luego en luminosidad percibida no lineal (L*
)PARA ENCONTRAR LA LUMINANCIA:
... Porque aparentemente se perdió en alguna parte ...
Paso uno:
Convierta todos los valores enteros de 8 bits sRGB a decimal 0.0-1.0
Segundo paso:
Convierta un RGB codificado en gamma a un valor lineal. sRGB (estándar de la computadora), por ejemplo, requiere una curva de potencia de aproximadamente V ^ 2.2, aunque la transformación "precisa" es:
Donde V´ es el canal R, G o B codificado en gamma de sRGB.
Pseudocódigo:
Paso tres:
Para encontrar la luminancia (Y) aplique los coeficientes estándar para sRGB:
Pseudocódigo que utiliza las funciones anteriores:
PARA ENCONTRAR LA LUZ PERCIBIDA:
Paso cuatro:
Tome la luminancia Y desde arriba y transfórmela en L *
Pseudocódigo:
L * es un valor de 0 (negro) a 100 (blanco) donde 50 es el "gris medio" perceptivo. L * = 50 es el equivalente de Y = 18.4, o en otras palabras, una tarjeta gris al 18%, que representa la mitad de una exposición fotográfica (zona V de Ansel Adams).
Referencias
IEC 61966-2-1:1999 Standard
Wikipedia sRGB
Wikipedia CIELAB
Wikipedia CIEXYZ
Preguntas frecuentes sobre Gamma de Charles Poynton
fuente
Luma=rgb2gray(RGB);LAB=rgb2lab(RGB);LAB(:,:,2:3)=0;PerceptualGray=lab2rgb(LAB);
L*a*b*
no tiene en cuenta una serie de atributos psicofísicos. El efecto Helmholtz-Kohlrausch es uno, pero hay muchos otros. CIELAB no es un modelo de evaluación de imagen "completo" de ninguna manera. En mi publicación estaba tratando de cubrir los conceptos básicos lo más completamente posible sin aventurarme en las minucias muy profundas. El modelo Hunt, los modelos de Fairchild y otros hacen un trabajo más completo, pero también son sustancialmente más complejos.Encontré este código (escrito en C #) que hace un excelente trabajo al calcular el "brillo" de un color. En este escenario, el código está tratando de determinar si se debe colocar texto blanco o negro sobre el color.
fuente
Curiosamente, esta formulación para RGB => HSV solo usa v = MAX3 (r, g, b). En otras palabras, puedes usar el máximo de (r, g, b) como V en HSV.
Verifiqué y en la página 575 de Hearn & Baker, así es como también calculan el "Valor".
fuente
En lugar de perderse entre la selección aleatoria de fórmulas mencionadas aquí, le sugiero que elija la fórmula recomendada por los estándares del W3C.
Aquí hay una implementación PHP sencilla pero exacta de las fórmulas de relación de luminancia relativa y contraste WCAG 2.0 SC 1.4.3 . Produce valores que son apropiados para evaluar las proporciones requeridas para el cumplimiento de WCAG, como en esta página , y como tal es adecuado y apropiado para cualquier aplicación web. Esto es trivial para portar a otros idiomas.
fuente
Para agregar lo que todos los demás dijeron:
Todas estas ecuaciones funcionan bastante bien en la práctica, pero si necesita ser muy preciso, primero debe convertir el color en un espacio de color lineal (aplicar gamma de imagen inversa), hacer el promedio de peso de los colores primarios y, si desea muestra el color: recupera la luminancia en el monitor gamma.
La diferencia de luminancia entre ignorar gamma y hacer gamma adecuada es de hasta 20% en los grises oscuros.
fuente
Estaba resolviendo una tarea similar hoy en JavaScript. Me he decidido por esta
getPerceivedLightness(rgb)
función para un color HEX RGB. Se trata del efecto Helmholtz-Kohlrausch a través de la fórmula Fairchild y Perrotta para la corrección de luminancia.fuente
El espacio de color HSV debería ser el truco, consulte el artículo de Wikipedia, dependiendo del idioma en el que esté trabajando, puede obtener una conversión de biblioteca.
H es un tono que es un valor numérico para el color (es decir, rojo, verde ...)
S es la saturación del color, es decir, cuán 'intenso' es
V es el 'brillo' del color.
fuente
Valor de luminancia RGB = 0.3 R + 0.59 G + 0.11 B
http://www.scantips.com/lumin.html
Creo que el espacio de color RGB es perceptiblemente no uniforme con respecto a la distancia euclidiana L2. Los espacios uniformes incluyen CIE LAB y LUV.
fuente
La fórmula de gamma inversa de Jive Dadson necesita que se elimine el medio ajuste cuando se implementa en Javascript, es decir, el retorno de la función gam_sRGB debe ser devuelto int (v * 255); no devuelve int (v * 255 + .5); La mitad del ajuste se redondea hacia arriba, y esto puede causar un valor demasiado alto en un R = G = B, es decir, una tríada de color gris. La conversión en escala de grises en una tríada R = G = B debería producir un valor igual a R; Es una prueba de que la fórmula es válida. Ver Nueve sombras de escala de grises para la fórmula en acción (sin el medio ajuste).
fuente
Me pregunto cómo se determinaron esos coeficientes rgb. Hice un experimento yo mismo y terminé con lo siguiente:
Cercano pero obviamente diferente a los coeficientes ITU establecidos desde hace mucho tiempo. Me pregunto si esos coeficientes podrían ser diferentes para cada observador, porque todos podemos tener una cantidad diferente de conos y bastones en la retina en nuestros ojos, y especialmente la relación entre los diferentes tipos de conos puede diferir.
Para referencia:
ITU BT.709:
ITU BT.601:
Hice la prueba moviendo rápidamente una pequeña barra gris sobre un fondo rojo brillante, verde brillante y azul brillante, y ajustando el gris hasta que se mezclara lo más posible. También repetí esa prueba con otros tonos. Repetí la prueba en diferentes pantallas, incluso una con un factor de gamma fijo de 3.0, pero todo me parece igual. Más aún, los coeficientes ITU son literalmente incorrectos para mis ojos.
Y sí, presumiblemente tengo una visión normal del color.
fuente
Aquí hay un poco de código C que debería calcular correctamente la luminancia percibida.
fuente
Por favor, defina el brillo. Si está buscando qué tan cerca está el color blanco, puede usar la distancia euclidiana desde (255, 255, 255)
fuente
La 'V' de HSV es probablemente lo que estás buscando. MATLAB tiene una función rgb2hsv y el artículo de wikipedia citado anteriormente está lleno de pseudocódigo. Si una conversión RGB2HSV no es factible, un modelo menos preciso sería la versión en escala de grises de la imagen.
fuente
Este enlace explica todo en profundidad, incluido por qué esas constantes multiplicadoras existen antes de los valores R, G y B.
Editar: tiene una explicación para una de las respuestas aquí también (0.299 * R + 0.587 * G + 0.114 * B)
fuente
Para determinar el brillo de un color con R, convierto el color del sistema RGB en color del sistema HSV.
En mi script, utilizo el código del sistema HEX antes por otra razón, pero también puede comenzar con el código del sistema RGB con
rgb2hsv {grDevices}
. La documentación está aquí .Aquí está esta parte de mi código:
fuente
Para mayor claridad, las fórmulas que usan una raíz cuadrada deben ser
sqrt(coefficient * (colour_value^2))
no
sqrt((coefficient * colour_value))^2
La prueba de esto radica en la conversión de una tríada R = G = B a escala de grises R. Eso solo será cierto si cuadras el valor del color, no el valor del color por el coeficiente. Ver Nueve sombras de escala de grises
fuente