Conversión de RGB a escala de grises/intensidad
Al convertir de RGB a escala de grises, se dice que se deben aplicar pesos específicos a los canales R, G y B. Estos pesos son: 0,2989, 0,5870, 0,1140.
Se dice que la razón de esto es la diferente percepción/sensibilidad humana hacia estos tres colores. A veces también se dice que estos son los valores utilizados para calcular la señal NTSC.
Sin embargo, no encontré una buena referencia para esto en la web. ¿Cuál es la fuente de estos valores?
Ver también estas preguntas anteriores: aquí y aquí .
Los números específicos de la pregunta son del CCIR 601 (consulte el artículo de Wikipedia ).
Si convierte RGB -> escala de grises con números ligeramente diferentes/métodos diferentes, no verá mucha diferencia en una pantalla de computadora normal en condiciones de iluminación normales; pruébelo.
Aquí hay algunos enlaces más sobre el color en general:
wikipedia luma
El excelente sitio web de Bruce Lindbloom
capítulo 4 sobre Color en el libro de Colin Ware, "Visualización de información", isbn 1-55860-819-2; Este enlace largo a Ware en books.google.com puede funcionar o no.
cambridgeincolor : "tutoriales excelentes y bien escritos sobre cómo adquirir, interpretar y procesar fotografías digitales utilizando un enfoque visual que enfatiza el concepto sobre el procedimiento"
Si se topa con RGB "lineal" versus "no lineal", aquí hay parte de una vieja nota para mí sobre esto. Repito, en la práctica no verás mucha diferencia.
### RGB -> ^gamma -> Y -> L*
En la ciencia del color, los valores RGB comunes, como en html rgb (10%, 20%, 30%), se denominan "no lineales" o con corrección gamma . Los valores "lineales" se definen como
Rlin = R^gamma, Glin = G^gamma, Blin = B^gamma
donde gamma es 2,2 para muchas PC. Los RGB habituales a veces se escriben como R' G' B' (R' = Rlin ^ (1/gamma)) (clic de lengua de los puristas), pero aquí dejaré el '.
El brillo en una pantalla CRT es proporcional a RGBlin = RGB ^ gamma, por lo que el 50 % de gris en una CRT es bastante oscuro: 0,5 ^ 2,2 = 22 % del brillo máximo. (Las pantallas LCD son más complejas; además, algunas tarjetas gráficas compensan la gamma).
Para obtener la medida de luminosidad obtenida L*
desde RGB, primero divida RGB por 255 y calcule
Y = .2126 * R^gamma + .7152 * G^gamma + .0722 * B^gamma
Esto está Y
en el espacio de color XYZ; es una medida de la "luminancia" del color. (Las fórmulas reales no son exactamente x^gamma, pero se acercan; quédese con x^gamma para una primera pasada).
Finalmente,
L* = 116 * Y ^ 1/3 - 16
"... aspira a la uniformidad perceptiva [y] se acerca mucho a la percepción humana de la ligereza". -- Espacio de color del laboratorio de Wikipedia
Encontré esta publicación a la que se hace referencia en una respuesta a una pregunta similar anterior. Es muy útil y la página tiene varias imágenes de muestra:
Evaluación perceptiva de conversiones de imágenes de color a escala de grises por Martin Čadík, Foro de gráficos por computadora, volumen 27, 2008
La publicación explora varios otros métodos para generar imágenes en escala de grises con diferentes resultados:
- CIE Y
- Color2Gris
- Descolorizar
- herrero08
- rasche05
- bala04
- Neumann07
Curiosamente, concluye que no existe un método de conversión universalmente mejor, ya que cada uno funcionó mejor o peor que otros dependiendo de la entrada.
Aquí hay un código en c para convertir rgb a escala de grises. La ponderación real utilizada para la conversión de rgb a escala de grises es 0,3R+0,6G+0,11B. Estos pesos no son absolutamente críticos, así que puedes jugar con ellos. Los he hecho 0.25R+ 0.5G+0.25B. Produce una imagen ligeramente más oscura.
NOTA: El siguiente código asume el formato de píxeles xRGB de 32 bits
unsigned int *pntrBWImage=(unsigned int*)..data pointer..; //assumes 4*width*height bytes with 32 bits i.e. 4 bytes per pixel
unsigned int fourBytes;
unsigned char r,g,b;
for (int index=0;index<width*height;index++)
{
fourBytes=pntrBWImage[index];//caches 4 bytes at a time
r=(fourBytes>>16);
g=(fourBytes>>8);
b=fourBytes;
I_Out[index] = (r >>2)+ (g>>1) + (b>>2); //This runs in 0.00065s on my pc and produces slightly darker results
//I_Out[index]=((unsigned int)(r+g+b))/3; //This runs in 0.0011s on my pc and produces a pure average
}