miércoles, 6 de febrero de 2013

Filtros básicos

La tarea para esta entrada es modificar una imagen aplicándole filtros o efectos básicos como:

  • escala de grises
  • umbral (binarización)
  • negativo (invierte los colores)
  • difuminado (promedio)
  • espejo (cambia el sentido de la imagen)
Utilizando Python y sus librerías PIL y Tkinter.

Además de hacer una interfaz gráfica para poder modificar la imagen y poder verla fácilmente. Esta es la foto de ejemplo con la que trabajé:


La interfaz se ve de la siguiente manera:


Aplicando el filtro de escala de grises:


Así se ve al aplicar varias veces el filtro de promedio, que toma los píxeles de arriba, abajo, izquierda, derecha y el mismo para sacar un promedio y obtener el valor del pixel nuevo:

Promedio primera vez:

Promedio sexta vez:



Promedio 12va vez:


El umbral se ve de la siguiente manera, aplicado a la imagen original:



y en la siguiente primero apliqué varias veces el promedio y después el umbral, podemos apreciar la imagen menos detallada pero se pueden distinguir los elementos principales:



El de invertir colores, lo que hace es tomar 255 y restarle el color del pixel:


Efecto de invertido combinado con otros:


Y por último el de espejo, es solo un efecto que parece estar viendo la imagen como en un reflejo, yo lo apliqué solamente en un sentido, pero es muy  fácil hacerlo en los 4, lo hice solo con el propósito de jugar un poco más con los píxeles:



En la aplicación es posible regresar a la imagen original, y/o guardar la imagen además de poderse aplicar filtros encima de otros. Si se aplica un efecto antes de aplicar el de escala de grises, automáticamente se hace manda a llamar al método de escala de grises ya que el propósito es trabajar siempre con imágenes en escala de grises.

El código se encuentra con el nombre de archivo practica_1.py:

#!/usr/bin/python
#import Tkinter
#import time
from Tkinter import *
from PIL import Image, ImageTk
from math import floor
import sys
class Aplicacion:
"""clase que dibuja la interfaz y da la funcionalidad
de filtros
"""
def __init__(self, master, imagen_path):
self.nombre_imagen = imagen_path
self.imagen_original = self.abrir_imagen_original()
self.imagen_actual = self.imagen_original
self.x, self.y = self.imagen_original.size
self.master = master
self.frame = Frame(self.master)
self.frame.pack()
#se posicionan los botones
self.gris = Button(self.frame, text="gris", fg="blue",
command=self.hacer_gris)
self.umbral = Button(self.frame, text="umbral", fg="blue",
command=self.umbral)
self.invertido = Button(self.frame, text="invertir", fg="blue",
command=self.invertir)
self.promedio = Button(self.frame, text="promedio", fg="blue",
command=self.hacer_difusa)
self.espejo = Button(self.frame, text="espejo", fg="blue",
command=self.espejo)
self.reset = Button(self.frame, text="reset", fg="blue",
command=self.reiniciar)
self.guarda = Button(self.frame, text="guardar", fg="blue",
command=self.guardar)
self.gris.grid(row=0, column=0,padx=15, pady=15)
self.umbral.grid(row=0, column=1,padx=15, pady=15)
self.invertido.grid(row=0, column=2,padx=15, pady=15)
self.promedio.grid(row=0, column=3,padx=15, pady=15)
self.espejo.grid(row=0, column=4,padx=15, pady=15)
self.reset.grid(row=0, column=5,padx=15, pady=15)
self.guarda.grid(row=0, column=6,padx=15, pady=15)
#se abre la imagen
foto = Image.open(imagen_path)
foto = ImageTk.PhotoImage(foto)
self.picture = Label(self.frame, image=foto)
self.picture.image = foto
self.picture.grid(row=1, column=0, columnspan=7,sticky=W+E+N+S, padx=5, pady=5)
def abrir_imagen_original(self):
"""funcion que se manda llamar para
poder usar la imagen que se selecciono
al inicio
"""
imagen = Image.open(self.nombre_imagen)
imagen = imagen.convert('RGB')
return imagen
def reiniciar(self):
"""
funcion que regresa la foto al estado inicial
"""
self.imagen_actual = self.imagen_original
self.actualizar_imagen()
def guardar(self):
"""guarda la imagen con el nombre
imagen_nueva.png
"""
self.imagen_actual.save("imagen_nueva.png")
def actualizar_imagen(self):
"""redibuja la foto en la ventana
"""
foto = ImageTk.PhotoImage(self.imagen_actual)
self.picture = Label(self.frame, image=foto)
self.picture.image = foto
self.picture.grid(row=1, column=0, columnspan=7,sticky=W+E+N+S, padx=5, pady=5)
def espejo(self):
"""cambia el sentido de la imagen
"""
imagen_espejo = Image.new("RGB", (self.x, self.y))
pixeles = []
for a in range(self.y):
renglon = []
for b in range(self.x):
pixel = self.imagen_actual.getpixel((b, a))[0]
data = (pixel, pixel, pixel)
renglon.append(data)
renglon.reverse()
pixeles = pixeles + renglon
imagen_espejo.putdata(pixeles)
#se actualiza la imagen actual y se redibuja
self.imagen_actual = imagen_espejo
self.actualizar_imagen()
return imagen_espejo
def hacer_gris(self):
"""pone la foto en escala de grises
toma el valor maximo del rgb de cada pixel
"""
imagen_gris = Image.new("RGB", (self.x, self.y))
pixeles = []
for a in range(self.y):
for b in range(self.x):
r, g, b = self.imagen_actual.getpixel((b, a))
rgb = (r, g, b)
#se elige el valor mas grande
maximo = max(rgb)
data = (maximo, maximo, maximo)
pixeles.append(data)
imagen_gris.putdata(pixeles)
#se actualiza la imagen actual y se redibuja
self.imagen_actual = imagen_gris
self.actualizar_imagen()
return imagen_gris
def umbral(self):
"""binariza la imagen si el valor del pixel es de color menor a
150 se pone 0 en el pixel, si es mayo se pone 255 en el pixel
"""
imagen_umbral = Image.new("RGB", (self.x, self.y))
pixeles = []
for a in range(self.y):
for b in range(self.x):
color = self.imagen_actual.getpixel((b,a))[0]
if color > 127:
color = 255
else:
color = 0
data = (color, color, color)
pixeles.append(data)
imagen_umbral.putdata(pixeles)
self.imagen_actual = imagen_umbral
self.actualizar_imagen()
return imagen_umbral
def invertir(self):
"""cambia los colores de la imagen a su contrario
restando 255 a cada pixel
"""
imagen_invertida = Image.new("RGB", (self.x, self.y))
pixeles = []
for a in range(self.y):
for b in range(self.x):
color = self.imagen_actual.getpixel((b,a))[0]
color = 255 - color
data = (color, color, color)
pixeles.append(data)
imagen_invertida.putdata(pixeles)
#se actualiza la imagen actual y se redibuja
self.imagen_actual = imagen_invertida
self.actualizar_imagen()
return imagen_invertida
def hacer_difusa(self):
"""funcion que se encarga de tomar de cada pixel los pixeles
de izq, derecha, arriba, abajo y el mismo y los promedia, y ese
promedio es el valor de los nuevos pixeles
"""
imagen_difusa = Image.new("RGB", (self.x, self.y))
pixeles = []
#temp sirve para obtener el promedio de los
#pixeles contiguos
temp = []
for a in range(self.y):
for b in range(self.x):
actual = self.imagen_actual.getpixel((b, a))[0]
if b>0 and b<(self.x-1) and a>0 and a<(self.y-1):
#en esta condicion entran todos los pixeles que no estan
#en el margen de la imagen, es decir casi todos
pix_izq = self.imagen_actual.getpixel((b-1, a))[0]
pix_der = self.imagen_actual.getpixel((b+1, a))[0]
pix_arriba = self.imagen_actual.getpixel((b, a+1))[0]
pix_abajo = self.imagen_actual.getpixel((b, a-1))[0]
temp.append(pix_izq)
temp.append(pix_der)
temp.append(pix_arriba)
temp.append(pix_abajo)
else:
#aqui entran todos los pixeles de la orilla
try:
pix_abajo = self.imagen_actual.getpixel((b, a-1))[0]
temp.append(pix_abajo)
except:
pass
try:
pix_der = self.imagen_actual.getpixel((b+1, a))[0]
temp.append(pix_der)
except:
pass
try:
pix_izq = self.imagen_actual.getpixel((b-1, a))[0]
temp.append(pix_izq)
except:
pass
try:
pix_arriba = self.imagen_actual.getpixel((b, a+1))[0]
temp.append(pix_arriba)
except:
pass
temp.append(actual)
#se obtiene el promedio para cambiar el pixel
prom = sum(temp)/len(temp)
temp = []
pixeles.append((prom, prom, prom))
imagen_difusa.putdata(pixeles)
#se actualiza la imagen actual y se redibuja
self.imagen_actual = imagen_difusa
self.actualizar_imagen()
return imagen_difusa
def main():
"""funcion principal
"""
try:
imagen_path = sys.argv[1]
print imagen_path
except:
print "No seleccionaste una imagen"
return
root = Tk()
App = Aplicacion(root, imagen_path)
root.title("Imagenes")
root.mainloop()
if __name__ == "__main__":
main()
view raw Filtros hosted with ❤ by GitHub

1 comentario: