Social Icons

twitterfacebookgoogle plusemail

jueves, 9 de mayo de 2013

Detección de esquinas

En esta entrada hablare sobre la detección de esquinas, para ello lo primero que debemos realizar es un filtro mediano de los pixeles en la imagen después de obtener una diferencia de la imagen filtrada vs. la original (esto para disminuir el ruido que hay en la imagen) luego de haber obtenido la diferencia, esta se normaliza con la imagen, para así obtener las esquinas en la imagen que en este caso yo pondré pixeles de color blanco para representar una esquina.

Veamos primero el código explicado.

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.

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.


1 comentarios:

  1. 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