¿Cuáles son las diferencias prácticas cuando se trabaja con colores en un espacio RGB lineal frente a un no lineal?


¿Cuál es la propiedad básica de un espacio RGB lineal y cuál es la propiedad fundamental de un espacio no lineal? Cuando se habla de los valores dentro de cada canal en esos 8 (o más) bits, ¿qué cambia?

En OpenGL, los colores son valores de 3+1, y con esto me refiero a RGB+alfa, con 8 bits reservados a cada canal, y esta es la parte que obtengo claramente.

Pero cuando se trata de corrección gamma no entiendo cuál es el efecto de trabajar en un espacio RGB no lineal.

Desde que saber cómo usar una curva en un software gráfico para la edición de fotos, mi explicación es que en un espacio RGB lineal se toman los valores tal como son, sin manipulación y sin función matemática adjunta, en lugar cuando no es lineal, cada canal generalmente evoluciona siguiendo un comportamiento clásico de la función de potencia.

Incluso si tomo esta explicación como la real, todavía no entiendo lo que es un espacio lineal real, porque después del cálculo todos los espacios RGB no lineales se vuelven lineales y lo más importante de todo no entiendo la parte donde un espacio de color no lineal es más adecuado para el ojo humano porque al final todos los espacios RGB son lineales para lo que entiendo.

Author: Michael Mullany, 2012-09-21

2 answers

Digamos que estás trabajando con colores RGB: cada color se representa con tres intensidades o brillos. Tienes que elegir entre" linear RGB "y"sRGB". Por ahora, simplificaremos las cosas ignorando las tres intensidades diferentes, y asumiremos que solo tienes una intensidad: es decir, solo estás tratando con tonos de gris.

En un espacio de color lineal, la relación entre los números que almacena y las intensidades que representan es lineal. Prácticamente, esto significa que si doblas el número, doblas la intensidad (la ligereza del gris). Si desea agregar dos intensidades juntas (porque está calculando una intensidad basada en las contribuciones de dos fuentes de luz, o porque está agregando un objeto transparente sobre un objeto opaco), puede hacer esto simplemente agregando los dos números juntos. Si está haciendo cualquier tipo de mezcla 2D o sombreado 3D, o casi cualquier procesamiento de imágenes, entonces desea que sus intensidades sean lineales color-space , por lo que solo puede sumar, restar, multiplicar y dividir números para tener el mismo efecto en las intensidades. La mayoría de los algoritmos de procesamiento de color y representación solo dan resultados correctos con RGB lineal, a menos que agregue pesos adicionales a todo.

Eso suena muy fácil, pero hay un problema. La sensibilidad del ojo humano a la luz es más fina a bajas intensidades que a altas intensidades. Es decir, si haces una lista de todas las intensidades que puedes distinguir, hay más oscuros que claros. Para decirlo de otra manera, puede distinguir los tonos oscuros de gris mejor que con los tonos claros de gris. En particular, si estás usando 8 bits para representar tu intensidad, y lo haces en un espacio de color lineal, terminarás con demasiados tonos claros y no suficientes tonos oscuros. Obtienes bandas en tus áreas oscuras, mientras que en tus áreas claras, estás desperdiciando bits en diferentes tonos de blanco cercano que el usuario no puede distinguir.

Para evitar este problema, y hacer el mejor uso de esos 8 bits, tendemos a usar sRGB . El estándar sRGB le indica una curva para usar, para hacer que sus colores no sean lineales. La curva es menos profunda en la parte inferior, por lo que puede tener más grises oscuros, y más empinada en la parte superior, por lo que tiene menos grises claros. Si doblas el número, doblas más que la intensidad. Esto significa que si agrega colores sRGB juntos, termina con un resultado que es más ligero de lo que debería ser. En estos días, la mayoría de los monitores interpretan sus colores de entrada como sRGB. Entonces, cuando estás poniendo un color en la pantalla, o almacenándolo en una textura de 8 bits por canal, almacénalo como sRGB, para que hagas el mejor uso de esos 8 bits.

Notará que ahora tenemos un problema: queremos que nuestros colores se procesen en espacio lineal, pero se almacenen en sRGB. Esto significa que termina haciendo la conversión de sRGB a lineal en lectura, y la conversión de lineal a sRGB en escritura. Como ya hemos dicho que las intensidades lineales de 8 bits no tienen suficientes sombras, esto causaría problemas, por lo que hay una regla práctica más: no use colores lineales de 8 bits si puede evitarlo. Se está volviendo convencional seguir la regla de que los colores de 8 bits siempre son sRGB, por lo que hace su conversión de sRGB a lineal al mismo tiempo que amplía su intensidad de 8 a 16 bits, o de entero a punto flotante; del mismo modo, cuando haya terminado su procesamiento de punto flotante, se reduce a 8 bits al mismo tiempo que la conversión a sRGB. Si sigues estas reglas, nunca tendrás que preocuparte por corrección gamma.

Cuando esté leyendo una imagen sRGB y desee intensidades lineales, aplique esta fórmula a cada intensidad:

float s = read_channel();
float linear;
if (s <= 0.04045) linear = s / 12.92;
else linear = pow((s + 0.055) / 1.055, 2.4);

Yendo hacia el otro lado, cuando desee escribir una imagen como sRGB, aplique esta fórmula a cada intensidad lineal:

float linear = do_processing();
float s;
if (linear <= 0.0031308) s = linear * 12.92;
else s = 1.055 * pow(linear, 1.0/2.4) - 0.055; ( Edited: The previous version is -0.55 )

En ambos casos, el valor de punto flotante s varía de 0 a 1, por lo que si estás leyendo enteros de 8 bits quieres dividir por 255 primero, y si estás escribiendo enteros de 8 bits quieres multiplicar por 255 último, de la misma manera que normalmente lo haría. Eso es todo lo que necesitas saber para trabajar con sRGB.

Hasta ahora, he tratado con una sola intensidad, pero hay cosas más inteligentes que hacer con los colores. El ojo humano puede distinguir diferentes brillos mejor que diferentes tintes (más técnicamente, tiene mejor resolución de luminancia que crominancia), por lo que puede hacer un mejor uso de sus 24 bits almacenando el brillo por separado del tinte. Esto es lo que YUV, YCrCb, etc. representaciones tratan de hacer. El canal Y es la luminosidad general del color, y utiliza más bits (o tiene más resolución espacial) que los otros dos canales. De esta manera, no necesita (siempre) aplicar una curva como lo hace con intensidades RGB. YUV es un espacio de color lineal, por lo que si duplica el número en el canal Y, duplica la luminosidad del color, pero no puede agregar o multiplicar los colores YUV juntos como puede hacerlo con los colores RGB, por lo que no se utiliza para el procesamiento de imágenes, solo para el almacenamiento y la transmisión.

Creo que responde a tu pregunta, así que terminaré con una breve nota histórica. Antes del sRGB, los CRT antiguos solían tener una no linealidad incorporada. Si duplicara el voltaje de un píxel, duplicaría la intensidad. Cuánto más era diferente para cada monitor, y este parámetro se llamó gamma . Este comportamiento fue útil porque significaba que podía obtener más oscuros que luces, pero también significaba que no podía saber qué tan brillantes serían sus colores en el CRT del usuario, a menos que lo calibré primero. Corrección gamma significa transformar los colores con los que comienzas (probablemente lineales) y transformarlos para la gamma del CRT del usuario. OpenGL proviene de esta era, por lo que su comportamiento sRGB a veces es un poco confuso. Pero los proveedores de GPU ahora tienden a trabajar con la convención que describí anteriormente: que cuando se almacena una intensidad de 8 bits en una textura o framebuffer, es sRGB, y cuando se procesan colores, es lineal. Por ejemplo, un OpenGL ES 3.0, cada uno framebuffer y texture tienen una "bandera sRGB" que puede activar para habilitar la conversión automática al leer y escribir. No es necesario hacer explícitamente la conversión sRGB o la corrección gamma en absoluto.

 154
Author: Dan Hulme,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-21 08:15:50

No soy un "experto en detección de color humano", pero he conocido algo similar en la conversión YUV->RGB. Hay diferentes pesos para los canales R/G/B, por lo que si cambia el color de origen por x, los valores RGB cambian diferente cantidad.

Como se ha dicho, no soy un experto, de todos modos, creo que, si desea hacer alguna transformación de color correcto, debe hacerlo en el espacio YUV, luego convertirlo a RGB (o hacer la operación matemáticamente equivalente en RGB, tenga cuidado con la pérdida de datos). Además, no estoy seguro de que YUV es la mejor representación nativa de colores, pero las cámaras de video proporcionan ese formato, ahí es donde he conocido el problema.

Aquí está la fórmula mágica YUV - > RGB con números secretos incluidos: http://www.fourcc.org/fccyvrgb.php

 1
Author: ern0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-15 09:58:51