Veamos primero el código explicado.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from PIL import ImageDraw | |
from sys import argv | |
import numpy as np | |
from math import ceil, floor, fabs | |
from Tkinter import * | |
import Image | |
import ImageTk | |
#Metodo que diferencia los pixeles de una imagen con otra | |
def diferencia(image, copy): | |
#Toma las medidas de la imagen | |
width, height = image.size | |
#Convierte la imagen en escala de grises | |
image = image.convert('L') | |
#Convierte la imagen en escala de grises | |
copy = copy.convert('L') | |
#Se crea una matriz de ceros con las medidas obtenidas anteriormente | |
matriz = np.zeros(( width, height )) | |
#Se carga la imagen para poder manipular los pixeles | |
img = image.load() | |
#Se carga la imagen para poder manipular los pixeles | |
img_copy = copy.load() | |
#Se iteran las medidas tomadas de la imagen | |
for y in xrange(height): | |
for x in xrange(width): | |
#Se hace la diferencia del pixel de una imagen con la copia | |
matriz[x, y] = img_copy[x,y] - img[x,y] | |
#Nos regresa una matriz con el resultado de la diferencia | |
return matriz | |
#Metodo que normaliza los pixeles de una imagen a partir de una matriz | |
def normalizaMatriz(matriz, imagen): | |
#Toma las medidas de la imagen | |
width, height = imagen.size | |
#Convierte la imagen en rgb | |
imagen = imagen.convert('RGB') | |
#Carga la imagen para poder manipular los pixeles | |
img = imagen.load() | |
#Se toman las medidas de la matriz | |
height, width = matriz.shape | |
#Se itera la matriz con las medidas tomadas | |
for y in xrange(height): | |
for x in xrange(width): | |
#Si el valor de la matriz es mayor a 0 | |
if fabs(matriz[y, x]) > 0: | |
#Se le asigna un pixel blanco | |
aux = 255 | |
else: | |
#Se le asigna un pixel negro | |
aux = 0 | |
img[y, x] = aux, aux, aux | |
#Nos regresa una imagen manipulada | |
return Image.fromarray(np.array(imagen)) | |
#Metodo que obtiene el filtro mediano de una imagen | |
def filtroMediano(original): | |
#Se obtienen las medidas de la imagen | |
width, height = original.size | |
#Se convierte la imagen en escala de grises | |
imagen = original.convert('L') | |
#Se carga la imagen para poder manipular los pixeles | |
img = imagen.load() | |
#Se crea una nueva imagen en escala de grises | |
copia = Image.new(mode='L', size=(width, height)) | |
#Se carga la imagen para poder manipular los pixeles | |
cp = copia.load() | |
#Se iteran los vecinos y se obtiene la mediana | |
for y in xrange(height): | |
for x in xrange(width): | |
vecinos = list() | |
#Se visitan los vecinos del pixel de la imagen actual | |
for i in [-1, 0, 1]: | |
for j in [-1, 0, 1]: | |
#Se agrega a una lista de vecinos los valores | |
try: | |
vecinos.append( img[ x+i , y+j ] ) | |
except: | |
pass | |
#Se ordena la lista | |
vecinos.sort() | |
#Se obtiene la mediana de la lista y se coloca en el pixel de la copia | |
cp[x,y] = vecinos[len(vecinos) / 2] | |
#Nos regresa una imagen donde se ha puesto el resultado de la mediana | |
return Image.fromarray(np.array(copia)) | |
#Metodo para mostrar imagen con interfaz grafica | |
def tk(imagen): | |
root = Tk() | |
width, height = imagen.size | |
canvas = Canvas(root, width=width, height=height) | |
canvas.pack(expand=YES, fill=BOTH) | |
imagen_canvas = ImageTk.PhotoImage(imagen) | |
imagen_canvas_setting = canvas.create_image((2, 2), image=imagen_canvas, anchor=NW) | |
root.mainloop() | |
return | |
def main(): | |
#Obtiene la imagen | |
imagen = Image.open(argv[1]) | |
#Se hace un filtro mediano de la imagen y se obtiene una copia de la imagen | |
copy = filtroMediano(imagen) | |
#Se obtiene la diferencia de la imagen original con la copia de la imagen | |
matriz_diferencia = diferencia(imagen, copy) | |
#Se normaliza la diferencia con la imagen original | |
imgfiltrada = normalizaMatriz(matriz_diferencia, imagen) | |
return tk(imgfiltrada) | |
main() |
Para correr simplemente agregamos como parámetro la ruta de la imagen.
Haremos una prueba con la siguiente imagen.
Y lo que obtenemos es lo siguiente, resaltando que los pixeles blancos son las esquinas.
Una cosas curiosa fue haber detectado el círuclo y generar rayos cada 45 grados. Existen formas para mejorar la detección de las esquinas en este caso lo que hice fue hacer un filtro gaussiano para poder hacer que cada punto (sí existe solamente un pixel no visible a simple vista) pueda aumentar su visibilidad.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def filtroGaussiano(imagen): | |
width, height = imagen.size | |
original = imagen.convert('L') | |
copia = Image.new(mode='L', size=(width, height)) | |
org = original.load() | |
cp = copia.load() | |
contador = 0 | |
pixel = 0 | |
for y in xrange(height): | |
for x in xrange(width): | |
for i in [-1, 0, 1]: | |
for j in [-1, 0, 1]: | |
try: | |
pixel += org[ x*i , y*j ] | |
contador+=1 | |
except: | |
pass | |
print pixel | |
cp[x,y] = pixel / ( contador * 1.0) | |
contador = 0 | |
pixel = 0 | |
return Image.fromarray(np.array(copia)) |
Ahora se realizó una prueba con la imagen anterior usando un filtro gaussiano.
Ahora mostraré un conjunto de pruebas realizadas detectando las esquinas usando un filtro gaussiano.
Prueba 1.
Prueba 2.
Faltó limpiar un poco los resultados para que cada esquina sea representado por una mancha y también faltó el wireframe. Pero los del filtro sí agarra decentemente, lo que era la parte obligatoria. 7 pts.
ResponderEliminar