Social Icons

twitterfacebookgoogle plusemail

lunes, 18 de febrero de 2013

Tarea 2: Detección de líneas

Esta entrada trata sobre detección de líneas usando un algoritmo de BFS (Breath First Search) es un algoritmo para recorrer grafos (nuestra imágen), el cual recorre un color en específico de cada pixel, hasta visitar todos los vecinos (en donde cada vecino tiene que ser del mismo color). Para realizar esta tarea se tuvo que haber obtenido un filtro de binarizacion para poder extraer varios objetos. A continuación veremos unos ejemplos, donde primero se muestra la imágen original y la imágen filtrada con la binarizada.





Código:

import numpy as np
import Tkinter
from PIL import ImageDraw
import Image
import ImageTk
from sys import argv
import time
from math import fabs
def convolucion(imagen, h):
iwidth, iheight = imagen.size
imagen = imagen.convert('L')
im = imagen.load()
mheight, mwidth = h.shape
print "Imagen size: ",imagen.size
print "H: ",h.shape
g = np.zeros(shape=(iheight, iwidth))
for x in xrange(iheight):
for y in xrange(iwidth):
sum = 0.0
for j in xrange(mheight):
zj = ( j - ( mheight / 2 ) )
for i in xrange(mwidth):
zi = ( i - ( mwidth / 2 ) )
try:
sum += im[y + zi, x + zj] * h[i,j]
except:
pass
#print x, y
g[x,y] = sum
#print "Convolucion"
#print g
return g
def filtro(original):
width, height = original.size
print width, height
original = original.convert('L')
modificado = Image.new(mode='L', size =(width,height))
org = original.load()
mod = modificado.load()
contador = 0
min = 0
max = 0
for y in xrange(height):
for x in xrange(width):
pixel = org[x,y]
if min >= pixel:
min = pixel
if max <= pixel:
max = pixel
print "MAX:",max," MIN:",min
for y in xrange(height):
for x in xrange(width):
pixel = org[x,y]
try:
pixel += org[x-1,y]
contador+=1
except:
None
try:
pixel += org[x+1,y]
contador+=1
except:
None
try:
pixel += org[x,y+1]
contador+=1
except:
None
try:
pixel += org[x,y-1]
contador+=1
except:
None
promedio = (pixel) / (contador)
r = max - min
prop = 256.0 / r
p = int((promedio -min) * prop)
if p <= 90:
mod[x,y] = 0
else:
mod[x,y] = 255
#print mod[x,y]
#print x,y
contador = 1
pixel = 0
data = np.array(modificado)
# print data
print data.shape
im = Image.fromarray(data)
return im
def filtroPorNumeros(im,n):
for x in xrange(n):
im = filtro(im)
return im
def escalaDeGrises(im):
width, height = im.size
print width, height
im = im.convert('RGB')
pix = im.load()
promedio = 0.0
for y in xrange(height):
for x in xrange(width):
r, g, b = pix[x, y]
promedio = (r + g + b) / 3.0
pix[x, y] = int(promedio), int(promedio), int(promedio)
data = np.array(im)
im2 = Image.fromarray(data)
return im2
def nuevaImagen(matriz):
height, width = matriz.shape
print matriz.shape
imagen = Image.new(mode='L', size =(width,height))
im = imagen.load()
print imagen.size
for x in xrange(height):
for y in xrange(width):
im[y, x] = matriz[x, y]
data = np.array(imagen)
#print data
im = Image.fromarray(data)
return im
#metodo breath first search
#toma como parametro la matriz de la imagen, una copia de la matriz
#el color asignado RGB, la cola que es una lista, el ancho y la
#altura de la imagen original
def bfs(imagen, copia, rgb, cola, width, height):
#toma el primer elemento de la cola y lo saca
(columna, fila) = cola.pop(0)
#si imagen no es color negro nos regresa un false
if not imagen[fila, columna] == 0:
return False
#toma como blanco el pixel en la cola
imagen[fila, columna] = 255 # ignora por poner en blanco
#toma el color rgb en variables separadas
(r, g, b) = rgb
copia[fila, columna] = r, g, b #asigna el color RGB en una copia
#se visitan los vecinos arriba, izquierda, derecha y abajo
for dx in [-1, 0, 1]:
for dy in [-1, 0, 1]:
if fabs(dx) + fabs(dy) == 1:
(px, py) = (columna + dx, fila + dy)
# se coloca un rango para no salir de las orillas
if px >= 0 and px < width and py >= 0 and py < height:
#se guarda el contenido del pixel
contenido = imagen[py, px]
#si es negro se agrega en la cola siempre y cuando
#no haya sido visitado
if contenido == 0: # solo los negros entran en la cola
if (px, py) not in cola:
cola.append((px, py))
return True
def asignColor(grupo):
return ((grupo * 5 + 7) % 256, (grupo * 13 + 41) % 256, (grupo * 29 + 13) % 256)
#Metodo para hacer deteccion de objetos
#toma como parametro el nombre de la imagen
def deteccionObjetos(imagen):
#Toma las proporciones de la imagen
height, width = imagen.size
#toma es escala de grises la imagen
imagen = imagen.convert('L')
#carga la imagen para manipularla
im = imagen.load()
#inicializa variables agregados y grupo
agregados = 0
grupo = 1
#asigna un color rgb dependiendo de lo que devuelva
#el metodo asignColor
rgb = asignColor(grupo)
#inicializa en 0 max y en fondo se pone como None
#porque aun no se conoce el fondo
max = 0
fondo = None
#se crea una imagen rgb con las proporciones de la
#imagen anterior
cp = Image.new(mode='RGB', size=(height, width))
#se obtiene el total de pixeles
total = width * height
# se carga la imagen creada en rgb
copia = cp.load()
# inicializa variable fondorgb
fondorgb = None
while True:
# se coloca como false un marcador
listo = False
#Se recorre según las proporciones
for y in xrange(height):
for x in xrange(width):
# si el pixel actual es negro
#el marcador se coloca en true
# y se sale del ciclo
if im[y, x] == 0: # negro
listo = True
break
if listo:
break
#si el marcador es falso sale del ciclo infinito
if not listo:
break
#se crea la cola
cola = list()
# agrega la coordenada donde se encuentra nuestro pixel
cola.append((x, y))
#se guardan los pixeles que han sido agregados
antes = agregados
#este ciclo seguira hasta que la cola no tenga nada
while len(cola) > 0:
#se hace breath first search
#tomando como parametro matriz de la imagen, la matriz creada en rgb
#la cola, el ancho y la altura de la imagen
if bfs(im, copia, rgb, cola, width, height):
#cada vez que se agregue un vecino nuevo se agrega un mas 1
agregados +=1
#se restan los pixeles agregados antes y los pixeles agregados actualmente en total
#esto nos dara el total de pixeles que quedan
pixeles = agregados - antes
#si pixeles es mayor a cero significa que es un grupo distinto
#ya que en nuestro caso el fondo es negro y la suma de ellos es 0
if pixeles > 0:
#en caso de entrar aqui significa que encontramos un nuevo grupo,
#osea otra figura
print 'Grupo %d tiene %d pixeles (%.0f por ciento)' \
% (grupo, pixeles, pixeles * 100.0 / total)
print rgb
#si pixeles es el maximo
# se asigna como maximo el nuevo valor
#y lo toma como fondo
#guarda una copia en rgb y una en L
if pixeles > max:
max = pixeles
fondo = grupo
fondorgb = rgb
#Se asigna un nuevo grupo, se asigna un color nuevo
grupo += 1
rgb = asignColor(grupo)
#verifica cual es que tuvo mayor densidad segun el color, la cual
#fue guardado en la variable fondo
print 'Grupo %d parece ser el fondo' % fondo
print fondorgb
c = 0
#Itera la altura y ancho de la imagen
# y asigna de otro color el fondo
for x in xrange(width):
for y in xrange(height):
r, g, b = copia[y, x]
fr, fg, fb = fondorgb
if r == fr and g == fg and b == fb:
c += 1
copia[y, x] == 200, 200, 200
print c, max
data = np.array(cp)
im = Image.fromarray(data)
return im
def binarizacion(imagen):
width, height = imagen.size
imagen = imagen.convert('L')
im = imagen.load()
for x in xrange(height):
for y in xrange(width):
pixel = im[y, x]
if pixel < 3:
im[y, x] = 0
else:
im[y, x] = 255
data = np.array(imagen)
im = Image.fromarray(data)
return im
def dibujaPuntos(stack, imagen):
draw = ImageDraw.Draw(imagen)
draw.polygon(stack, fill=None, outline=None)
return imagen
def main():
imagen = Image.open(argv[1])
original = imagen
escalaGrises = escalaDeGrises(imagen)
px = np.array([[-1,0,1], [-1,0,1], [-1,0,1]])
py = np.array([[1,1,1], [0,0,0], [-1,-1,-1]])
t1 = time.time()
gx = convolucion(escalaGrises, px)
gx = gx ** 2
gy = convolucion(escalaGrises, py)
gy = gy ** 2
g = (gx + gy ) ** 1.0/2.0
# print g
min = np.min(g)
max = np.max(g)
h, w = g.shape
minimos = np.ones(shape=(h, w))
minimos *= min
g = g - min
print "Restando el minimo", g
g = g / (max - min)
print "Dividiendo el max-min",g
print "Max: ",np.max(g)," Min: ",np.min(g)
bn = np.ones(shape=(h, w))
bn *= 255
g = g * bn
print "Max: ",np.max(g)," Min: ",np.min(g)
imagen_nueva = nuevaImagen(g)
imagen_binaria = binarizacion(imagen_nueva)
imagen_deteccionObjetos = deteccionObjetos(imagen_binaria)
#imagen_convexHull = dibujaPuntos(stack, imagen_convexHull)
root = Tkinter.Tk()
tkimageModf = ImageTk.PhotoImage(imagen_nueva)
tkimageOrig = ImageTk.PhotoImage(imagen_binaria)
tkimageDeteccionObjetos = ImageTk.PhotoImage(imagen_deteccionObjetos)
#Tkinter.Label(root, image = tkimageModf).pack(side="left")
Tkinter.Label(root, image = tkimageOrig).pack(side="right")
Tkinter.Label(root, image = tkimageDeteccionObjetos).pack(side="left")
t2 =time.time()
print "Tiempo total: ",t2-t1
root.mainloop()
main()
view raw gistfile1.py hosted with ❤ by GitHub

1 comentarios:

  1. El título de la entrada es el que deberías poner la semana que viene. Aplica el mismo comentario que a Raúl. 4 pts.

    ResponderEliminar