Etiqueta: escala de grises

Conversion de imagenes RGB a escala de grises con Python 3

Esta conversion se realiza calculando un equivalente «E» formado a partir de los tres planos de la imagen a color. En su forma mas sencilla se establece este equivalente como el promedio, es decir:

CodeCogsEqn

Podemos codificarlo de la siguiente manera:


from PIL import Image

foto = Image.open('ruta_y_nombre_del_archivo')

datos = foto.getdata()

#para el calculo del promedio se utilizara la division entera con el operador de division doble "//" para evitar decimales

promedio = [(datos[x][0] + datos[x][1] + datos[x][2]) // 3 for x in range(len(datos))]

imagen_gris = Image.new('L', foto.size)

imagen_gris.putdata(promedio)

imagen_gris.save('ruta_y_nombre_del_archivo')

foto.close()

imagen_gris.close()

 

Utilizando la imagen del logo de este blog revisaremos el resultado del codigo anterior:

logo
Imagen original

 

logo_gris_promedio
Resultado del metodo por promedio

 

La subjetiva iluminacion, propia del modelo RGB hace que utilizando el promedio las imagenes con un valor grande en la componente de rojo y/o verde tengan una apariencia obscura. El efecto contrario sucede donde el contenido del plano azul es grande, mostrando en su version a escala de grises una apariencia muy clara. Con el objetivo de solventar esto se considera como una mejor aproximacion calcular una combinacion lineal de todos los planos, definida como:

CodeCogsEqn

Donde WR, WG y WB son los coeficientes que definen la transformacion, los cuales de acuerdo al criterio utilizado en la TV para señales a color se consideran como:

WR=0.299     WG=0.587     WB=0.114

Justamente este es el metodo de conversion que provee el modulo Image de la biblioteca que hemos estado utilizando, el codigo es:


from PIL import Image

foto = Image.open('ruta_y_nombre_del_archivo')

imagen_gris = foto.convert('L')

imagen_gris.save('ruta_y_nombre_del_archivo')

foto.close()

imagen_gris.close()

 

logo_convert
Resultado del metodo convert(‘L’)

 

Otra alternativa sugerida en ITU-BT.709 para la codificacion digital del color considera:

WR=0.2125   WG=0.7154   WB=0.072

Una consideracion de importancia es la distorsion Gamma producida en las señales de TV que afecta de manera no lineal por lo que en lugar de los valores mostrados anteriormente se podria hacer uso de un nuevo set de coeficientes :

WR=0.309    WG=0.609    WB=0.082

Para cualquiera de los dos casos anteriores podriamos codificarlo asi:


from PIL import Image

foto = Image.open('ruta_y_nombre_del_archivo')

datos = list(foto.getdata())

#tomando el valor de los coeficientes de ITU-BT.709

grises = [round((0.2125 * datos[x][0]) + (0.7154 * datos[x][1]) + (0.072 * datos[x][2])) for x in range(len(datos))]

imagen_gris = Image.new('L', foto.size)

imagen_gris.putdata(grises)

imagen_gris.save('ruta_y_nombre_del_archivo')

foto.close()

imagen_gris.close()

 

logo_itu
Resultado de la imagen con los coeficientes del ITU-BT.709

 

Se observa que la imagen  por estos dos ultimos metodos es menos oscura que utilizando el promedio.

Peace

-Raziel