jueves, 18 de diciembre de 2014

Fundamentos para procesar imágenes con Pillow (y III)



Después de ver, en la primera parte de esta entrega, algunas funciones básicas de edición de imágenes del módulo Image de Pillow y, en la segunda parte, otras para convertir las imágenes y aplicar diferentes filtros, pasamos ahora a mostrar funciones del módulo ImageOps que se utilizan para añadir bordes a las imágenes y para aplicar efectos que crean imágenes inversas, espejadas, ecualizadas; o que permiten modificar sus colores, el contraste, etc.

Para finalizar se muestran algunos ejemplos que usan funciones del módulo ImageDraw que se utilizan para realizar dibujos vectoriales y escribir textos sobre una imagen.


Añadir bordes a una imagen


Para agregar un borde de color negro alrededor de la imagen de 5 píxeles de grosor:

from PIL import Image, ImageOps
imagen = Image.open("pantera.jpg")
imagen.size   # 800x600
imagen.mode   # RGB
imagenconborde = ImageOps.expand(imagen, border=5, fill=(0,0,255))
imagenconborde.show()
imagenconborde.save("panteraborde.jpg")




Lógicamente, si la imagen original tenía un tamaño de 800x600 ahora la obtenida será de 810x610, incrementándose en 5 píxeles cada margen de la imagen.

imagenconborde.size   # 810x610
imagenconborde = ImageOps.expand(imagen, border=5, fill="red")


La forma de asignar colores depende del tipo de imagen:

Tipo de imagenFormato color
1, L, Inúmero entero
RGBtupla con 3 números enteros (Rojo, Verdez y Azul) o nombres de color (en inglés)
Fnúmero entero o número de coma flotante
Pnúmero entero, tupla con 3 números enteros o nombres de color


Recortar los bordes de una imagen


La función crop() se utiliza para recortar las imágenes por todos sus márgenes un mismo número de píxeles:

recortar = ImageOps.crop(imagen, border=50)
recortar.show()




Convertir la imagen a escala de grises


grises = ImageOps.grayscale(imagen)
grises.show()



Obtener la imagen inversa

inversa = ImageOps.invert(imagen)
inversa.show()


 

Espejar una imagen (de izquierda a derecha)

espejo = ImageOps.mirror(imagen)
espejo.show()



Voltear una imagen verticalmente (de arriba a abajo)

flipeada = ImageOps.flip(imagen)
flipeada.show()



Reducir el número de bits para cada canal de color

posterizada = ImageOps.posterize(imagen, 1)
posterizada.show()



Invertir los valores de los píxeles por encima de un umbral

solarizada = ImageOps.solarize(imagen, threshold=64)
solarizada.show()



Maximizar contraste de una imagen (Autocontraste)




imagen = Image.open("nevando.jpg")
autocontraste = ImageOps.autocontrast(imagen, cutoff=0)
autocontraste.show()




La función calcula un histograma de la imagen de entrada y borra un porcentaje de los píxeles más claros y oscuros. Los píxeles más oscuros se convierten en negros (0) y los más claros en blancos (255).


Dar color a una imagen en blanco y negro



A los píxeles negros de la imagen se les asigna el primer color indicado en la función y a los píxeles blancos al segundo color.
imagen = Image.open("grises.jpg")
imagen.show()
coloriza = ImageOps.colorize(imagen, "black", "cyan")
coloriza.show()
coloriza.save("coloriza.jpg")




También, en este caso, es posible asignar un color RGB dando los valores en una tupla

coloriza = ImageOps.colorize(imagenbn, (0,0,0), (0,100,200))

Ecualizar una imagen


Ecualizar es sinónimo de igualar. En este caso la función iguala el histograma de la imagen de entrada aplicando un mapeo no lineal con el fin de crear una distribución uniforme de los valores en la escala de grises, en la imagen de salida.

imagen = Image.open("nevando.jpg")
ecualizada = ImageOps.equalize(imagen)
ecualizada.show()
ecualizada.save("ecualizada.jpg")



A continuación, los histogramas de la imagen sin ecualizar y de la ecualizada:




Otras funciones disponibles: deform(), fit(), flip()

Dibujar sobre una imagen

from PIL import Image, ImageDraw
imagen = Image.open("nevando.jpg")
dibujo = ImageDraw.Draw(imagen)
dibujo.line((0, 90) + (800, 90), fill="white")
imagen.show()
imagen.save("linea.jpg")




Otras funciones:

Dibujar punto:

ImageDraw.Draw.point(xy, fill=None)


Dibujar arco:

ImageDraw.Draw.arc(xy, start, end, fill=None)


Dibujar polígono:

ImageDraw.Draw.polygon([(x1, y1),(x2, y2),...], fill=None, outline=None)


Dibujar rectángulo:

Draw.rectangle([(x0, y0),(x1, y1)], fill=None, outline=None)


Dibujar bitmap

ImageDraw.Draw.bitmap(xy, bitmap, fill=None)


Dibujar elipse:

ImageDraw.Draw.ellipse(xy, fill=None, outline=None)


Escribir texto sobre una imagen


from PIL import Image, ImageDraw, ImageFont
imagen = Image.open("linea.jpg")
imagen = imagen.convert("RGBA")
texto = Image.new('RGBA', imagen.size, (255,255,255,0))
fuente = ImageFont.truetype("Arabic Magic.ttf", 40)
dibujo = ImageDraw.Draw(texto)
dibujo.text((10, 40), "Pillow", font=fuente, fill=(255,255,255,128))
dibujo.text((110,40), "Python", font=fuente, fill=(255,255,255,255))
final = Image.alpha_composite(imagen, texto)
final.show()
final.save("texto.jpg")





Cambiar tamaño de fuentes:



ImageDraw.Draw.textsize(text, font=None)


Hay fuentes para descargar en Fontriver.