En ésta entrada veremos como aplicar diferentes tipos de filtros a una determinada imagen, para eso se empleo python junto con la librería PIL, donde los filtros aplicados son:
- Escala de grises.
- Escala de grises mínimo.
- Escala de grises máximo.
- Negativo.
- Binaria.
El programa lo que hace es mostrarte en una ventana la imagen seleccionada, donde en la misma ventana te muestran botones para aplicar las diferentes tipos de escalas, al final dejo el código completo junto a la liga de github.
Algoritmo:
Para poder sacar los filtros primero se obtuvo cada pixel de la imagen, para después tener el rgb.
Escala de grises:
En la escala de grises, una vez obtenido el rgb del pixel, sacamos su media y este nuevo valor será el del rojo, verde y azul, para así obtener el nuevo pixel.
Escala de grises máximo y mínimo
En ésta escala de grises, lo que hago es obtener el pixel completo, sacando el máximo o mínimo del rgb, para después el obtenido ponerlo en cada rbg
Umbral:
El del umbral, interactúa un poco con el de la escala de grises, ya que nosotros pondremos un límite del valor obtenido (media), en mi caso si es mayor a 127 es 255, de lo contrario es 0.
Negativo:
Investigando un poco del algoritmo para sacar el negativo, lo que se hace es tener el valor maximo de un color (el cual es 255) y éste es restado por el valor de cada rgb, pra despues tener el pixel.
Para poder sacar los filtros primero se obtuvo cada pixel de la imagen, para después tener el rgb.
Escala de grises:
En la escala de grises, una vez obtenido el rgb del pixel, sacamos su media y este nuevo valor será el del rojo, verde y azul, para así obtener el nuevo pixel.
def grayScale(self): for i in range(self.img.size[0]): #recorremos las de i & j para tener cada pixel de la iamgen for j in range(self.img.size[1]): r = self.rgb.getpixel((i, j))[0] #obtenemos r, g, b g = self.rgb.getpixel((i, j))[1] b = self.rgb.getpixel((i, j))[2] media = (r+g+b)/3 #Lo explicado pixel = tuple([media, media, media]) #Creamos nuestro nuevo pixel self.img.putpixel((i, j), pixel) #En la imagen ponemos el nuevo pixel self.img.save('grayScale.png', 'PNG') #Guardamos la imagen return self.img #regresamos la imagen, para manipolarla posteriormente
[escala de grises]
Escala de grises máximo y mínimo
En ésta escala de grises, lo que hago es obtener el pixel completo, sacando el máximo o mínimo del rgb, para después el obtenido ponerlo en cada rbg
def grayScaleMax(self): for i in range(self.img.size[0]): #Se aplica lo mismo mencionado for j in range(self.img.size[1]): pixel = max(self.rgb.getpixel((i, j))) #Sacamos el máximo pixel = tuple([pixel, pixel, pixel]) self.img.putpixel((i, j), pixel) self.img.save('grayScaleMax.png', 'PNG') return self.img def grayScaleMin(self): for i in range(self.img.size[0]): for j in range(self.img.size[1]): pixel = min(self.rgb.getpixel((i, j))) #Sacamos en mínimo pixel = tuple([pixel, pixel, pixel]) self.img.putpixel((i, j), pixel) self.img.save('grayScaleMin.png', 'PNG') return self.img
[escala de grises mínimo]
[escala de grises máximo]
Umbral:
El del umbral, interactúa un poco con el de la escala de grises, ya que nosotros pondremos un límite del valor obtenido (media), en mi caso si es mayor a 127 es 255, de lo contrario es 0.
def binaryScale(self, umbral): if(umbral == None): umbral = 122 for i in range(self.img.size[0]): for j in range(self.img.size[1]): r = self.rgb.getpixel((i, j))[0] g = self.rgb.getpixel((i, j))[1] b = self.rgb.getpixel((i, j))[2] media = (r+g+b)/3 #Obtenemos la media pixel = tuple([media, media, media]) self.img.putpixel((i, j), pixel) if media > umbral: media = 255 #Dependiendo del umbral nos asigna el nuevo valor else: media = 0 pixel = tuple([media, media, media]) self.img.putpixel((i, j), pixel) self.img.save('BinaryScale.png', 'PNG') return self.img
[filtro binario]
Negativo:
Investigando un poco del algoritmo para sacar el negativo, lo que se hace es tener el valor maximo de un color (el cual es 255) y éste es restado por el valor de cada rgb, pra despues tener el pixel.
def negativeScale(self): for i in range(self.img.size[0]): for j in range(self.img.size[1]): r = self.rgb.getpixel((i, j))[0] g = self.rgb.getpixel((i, j))[1] b = self.rgb.getpixel((i, j))[2] nr = 255 - r # 255 que es nuestro valor máximo es restado por rgb ng = 255 - g nb = 255 - b pixel = tuple([nr, ng, nb]) self.img.putpixel((i,j), pixel) self.img.save('negativeScale.png', 'PNG') return self.img
[filtro negativo]
Al igual dejo el enlace de github.
from Tkinter import * from PIL import ImageTk, Image from sys import argv class Filtro(object): """docstring for Filtro""" def __init__(self, fileName): self.img = Image.open(fileName) self.rgb = self.img.convert('RGB') def grayScale(self): for i in range(self.img.size[0]): for j in range(self.img.size[1]): r = self.rgb.getpixel((i, j))[0] g = self.rgb.getpixel((i, j))[1] b = self.rgb.getpixel((i, j))[2] media = (r+g+b)/3 pixel = tuple([media, media, media]) self.img.putpixel((i, j), pixel) self.img.save('grayScale.png', 'PNG') return self.img def grayScaleMax(self): for i in range(self.img.size[0]): for j in range(self.img.size[1]): pixel = max(self.rgb.getpixel((i, j))) pixel = tuple([pixel, pixel, pixel]) self.img.putpixel((i, j), pixel) self.img.save('grayScaleMax.png', 'PNG') return self.img def grayScaleMin(self): for i in range(self.img.size[0]): for j in range(self.img.size[1]): pixel = min(self.rgb.getpixel((i, j))) pixel = tuple([pixel, pixel, pixel]) self.img.putpixel((i, j), pixel) self.img.save('grayScaleMin.png', 'PNG') return self.img def binaryScale(self, umbral): if(umbral == None): umbral = 122 for i in range(self.img.size[0]): for j in range(self.img.size[1]): r = self.rgb.getpixel((i, j))[0] g = self.rgb.getpixel((i, j))[1] b = self.rgb.getpixel((i, j))[2] media = (r+g+b)/3 pixel = tuple([media, media, media]) self.img.putpixel((i, j), pixel) if media > umbral: media = 255 else: media = 0 pixel = tuple([media, media, media]) self.img.putpixel((i, j), pixel) self.img.save('BinaryScale.png', 'PNG') return self.img def negativeScale(self): for i in range(self.img.size[0]): for j in range(self.img.size[1]): r = self.rgb.getpixel((i, j))[0] g = self.rgb.getpixel((i, j))[1] b = self.rgb.getpixel((i, j))[2] nr = 255 - r ng = 255 - g nb = 255 - b pixel = tuple([nr, ng, nb]) self.img.putpixel((i,j), pixel) self.img.save('negativeScale.png', 'PNG') return self.img path_image = sys.argv[1] debug = True imagen = Filtro(path_image)#Instanciamos la imagen de la clase filtro def main(): window() def window(): root = Tk() frame = Frame() frame.pack(fill=X, padx=5, pady=5) root.title("Imagen Original") call(Image.open(path_image)) #Ponemos la imagen original panel1 = Button(text="Original", command=original) panel1.pack(in_=frame, side=LEFT) panel2 = Button(text="GrayScale", command=grayScale) panel2.pack(in_=frame, side=LEFT) panel3 = Button(text="GrayScaleMin", command=grayScaleMin) panel3.pack(in_=frame, side=LEFT) panel4 = Button(text="GrayScaleMax", command=grayScaleMax) panel4.pack(in_=frame, side=LEFT) panel5 = Button(text="BinaryScale", command=binaryScale) panel5.pack(in_=frame, side=LEFT) panel6 = Button(text="Negative", command=negativeScale) panel6.pack(in_=frame, side=LEFT) root.mainloop() def call(im): #Metodo que ponemos la nueva imagen global panel img = ImageTk.PhotoImage(im) panel = Label(image = img) panel.pict = img panel.pack() def original(): #Metodo del Boton para llamar la imagen Original panel.destroy() #Destruimos el panel para poner la nueva imagen return call(Image.open(path_image)) def grayScale(): #Metodo del Boton para llamar la escala de grises global imagen panel.destroy() call(imagen.grayScale()) # de nuestro objeto imagen mandamos llamar la funcion def grayScaleMin(): #Metodo del Boton para llamar la escala de grises de min global imagen panel.destroy() call(imagen.grayScaleMin()) def grayScaleMax(): #Metodo del Boton para llamar la escala de grises de max global imagen panel.destroy() call(imagen.grayScaleMax()) def binaryScale(): #Metodo del Boton para llamar la escala binaria global imagen panel.destroy() call(imagen.binaryScale(None)) def negativeScale(): #Metodo del Boton para llamar la imagen en negativo global imagen panel.destroy() call(imagen.negativeScale()) if __name__ == '__main__': main()
Nota:
Debo de mencionar que me apoyé del crear y poner la imagen en la ventana del código de un compañero de clase, todo lo demás lo algorítmico del procesamiento de imagenes es de mi parte.
Referencias:
http://lodev.org/cgtutor/filtering.html
http://www.pythonware.com/library/tkinter/introduction/hello-again.htm
El código mejor incrustarlo con syntax highlighter y números de línea. Cuidado con los acentos de las palabras. Van 9 pts.
ResponderEliminarEXCELENTE !!
ResponderEliminar