Social Icons

twitterfacebookgoogle plusemail

jueves, 18 de abril de 2013

Relleno de elipses

En esta tarea intenté realizar un programa que realiza el BFS para rellenar los elipses, pero no funcionó como lo esperaba.


Así que opté por hacer un TODO list para saber que es lo que me falta por hacer:

Primero tengo que determinar bien los elipses obteniendo dos tangentes que crucen de los puntos obtenidos en el borde luego se obtiene el punto medio donde por medio de ellos obtenemos votos donde dichos votos nos ayudarán determinar si realmente estamos tratando con un elipse o no ya que si obtenemos gran cantidad de votos podemos obtener el centro de masa del elipse y aplicar un BFS.

import operator
import random
from math import fabs
from sys import argv
import numpy as np
from Tkinter import *
from PIL import ImageDraw, Image, ImageTk
def escalaGrises(imagen):
width, height = imagen.size
print "Este es el ancho: ", width, " altura: ",height
imagen = imagen.convert('RGB')
pixeles = imagen.load()
promedio = 0.0
for y in xrange(height):
for x in xrange(width):
r, g, b = pixeles[x, y]
promedio = ( r + g + b ) / 3.0
pixeles[x, y] = int( promedio ), int( promedio ), int( promedio )
datos = np.array(imagen)
imagen = Image.fromarray(datos)
return imagen
def convolucion(imagen, mascara):
width, height = imagen.size
imagen = imagen.convert('L')
pixeles = imagen.load()
mascara_height, mascara_width = mascara.shape
#print mascara.shape
g = np.zeros( shape = ( height, width ) )
for y in xrange(height):
for x in xrange(width):
sum = 0.0
for j in xrange(mascara_height):
zj = ( j - ( mascara_height / 2 ) )
for i in xrange(mascara_width):
zi = ( i - ( mascara_width / 2 ) )
try:
sum += pixeles[x + zi, y + zj] * mascara[j, i]
except:
pass
g[y, x] = sum
return g
def deteccionDeElipse(g, umbral, gx, gy, imagen):
width, height = imagen.size
imagen = imagen.convert('RGB')
pixeles = imagen.load()
#print "Gradiente x size: %s, Gradiente y size: %s "%(gx.shape, gy.shape)
borde = list()
margen = 50
print '%d por %d' % (width, height)
for y in xrange(margen, height - margen):
for x in xrange(margen, width - margen):
try:
if fabs(g[y, x]) > umbral:
borde.append((y, x))
#print '(%d, %d) es borde' % (y, x)
pixeles[y, x] = 0,255,0
except:
pass
print len(borde), 'son borde'
frec = dict()
pares = int(0.10 * len(borde))
print 'seleccionando', pares
for i in xrange(pares):
(y1, x1) = random.choice(borde)
(y2, x2) = random.choice(borde)
# print "Puntos para segmentoDeVotos( Pixel uno ( %d, %d ), Pixel dos ( %d, %d) ) "% (y1, x1, y2, x2)
votos = segmentoDeVotos((x1, height - y1), (gx[y1, x1], gy[y1, x1]), (x2, height - y2), (gx[y2, x2], gy[y2, x2]), width, height)
if votos is not None:
try:
pixeles[y1, x1] = 0,0,255
pixeles[y2, x2] = 0,0,255
except:
pass
for voto in votos:
if voto in frec:
frec[voto] += 1
else:
frec[voto] = 1
promedio = sum(frec.values()) / (1.0 * len(frec))
for y in xrange(height):
for x in xrange(width):
if (x, y) in frec:
f = frec[(x, y)]
if f > promedio:
# print "Estoy en pixel[ %s, %s] con ancho %d y altura %d" % (x, y, width, height)
try:
pixeles[y, x] = 255,0,0
except:
print "Fack"
datos = np.array(imagen)
imagen = Image.fromarray(datos)
return imagen
def puntoMedio(p1, p2):
(x1, y1) = p1
(x2, y2) = p2
return ((x1 + x2) / 2.0, (y1 + y2) / 2.0)
PASO = 0.001
def segmentoDeVotos(p1, g1, p2, g2, ancho, altura):
global PASO
#print "Punto 1: %s Punto 2: %s Grandiente 1: %s Gradiente 2: %s "%(p1, p2, g1, g2)
t1 = rectaTangente(p1, g1)
t2 = rectaTangente(p2, g2)
if t1 is None or t2 is None:
return None
#print "t1 %s, t2 %s"%(t1, t2)
cruceDeTangentes = cruceAntiparalelo(t1, t2)
if cruceDeTangentes is None:
return None
pm = puntoMedio(p1, p1)
recta = ecuacionDeRecta(cruceDeTangentes, pm)
if recta is None:
return None
(cx, cy) = cruceDeTangentes
(mx, my) = pm
dx = cx - mx
dy = cy - my
cambioX = PASO * dx
cambioY = PASO * dy
if dx < 0:
cambioX *= -1
if dy < 0:
cambioY *= -1
posX = mx
posY = my
votos = list()
while posX < ancho and posY < altura and posX > 0 and posY > 0:
pixel = (int(round(posX)), altura - int(round(posY)))
if not pixel in votos:
votos.append(pixel)
posX += cambioX
posY += cambioY
return votos
def rectaGradiente(coordenadasDePixel, gradiente):
(xg, yg) = gradiente
puntoAuxiliar = ( x + xg , y + yg )
return ecuacionDeRecta(coordenadasDePixel, puntoAuxiliar)
def rectaTangente(coordenadasDePixel, gradiente):
(xg, yg) = gradiente
(x, y) = coordenadasDePixel
puntoAuxiliar = (x + yg, y - xg)
# print "[rectaTangente] : Punto auxiliar %s, %s "%( (x+yg), (y -xg) )
return ecuacionDeRecta(coordenadasDePixel, puntoAuxiliar)
UMBRALCERO = 0.1
def cruceAntiparalelo(l1, l2):
global UMBRALCERO
(a1, b1) = l1
(a2, b2) = l2
if fabs(a1 - a2) < UMBRALCERO:
return None
# ax + b = y
x = (b2 - b1) / (1.0 * (a1 - a2))
y = a1 * x + b1
return (x, y)
def ecuacionDeRecta(p1, p2):
global UMBRALCERO
(x1, y1) = p1
(x2, y2) = p2
if fabs(x1 - x2) < UMBRALCERO:
return None
a = (y1 - y2) / (1.0 * (x1 - x2))
b = y1 - a * x1
return (a, b)
def coordenadas(lista):
coor = list()
for l in lista:
print l
c = l.split(' ')
coor.append((int(c[0]),int(c[1])))
return coor
def nuevaImagen(matriz):
height, width = matriz.shape
imagen = Image.new(mode='L', size = ( width, height ) )
pixeles = imagen.load()
for y in xrange(height):
for x in xrange(width):
pixeles[x, y] = matriz[y, x]
datos = np.array(imagen)
imagen = Image.fromarray(datos)
return imagen
def binario(imagen):
width, height = imagen.size
imagen = imagen.convert('L')
pixeles = imagen.load()
for y in xrange(height):
for x in xrange(width):
pixel = pixeles[x, y]
if pixel < 40: #Ajuste
pixeles[x, y] = 0
else:
pixeles[x, y] = 255
datos = np.array(imagen)
imagen = Image.fromarray(datos)
return imagen
def main():
imagen = Image.open( argv[1] )
imagen = escalaGrises( imagen )
px = np.array( [ [ -1, 0, 1 ], [ -2, 0, 2 ], [ -1, 0, 1 ] ] )
py = np.array( [ [ -1, -2, -1 ], [ 0, 0, 0 ], [ 1, 2, 1 ] ] )
gx = convolucion( imagen, px )
gy = convolucion( imagen, py )
gx_2 = gx ** 2
gy_2 = gy ** 2
g = ( gx_2 + gy_2 ) ** 0.5
ming = np.min(g)
maxg = np.max(g)
umbral = 0.5 * (maxg + ming) / 2.0
print 'umbral', umbral, ming, maxg
h, w = g.shape
minimos = np.ones( shape=( h, w ) )
minimos *= ming
gn = g - ming
gn = gn / ( maxg - ming )
bn = np.ones( shape=( h, w) )
bn *= 255
gn = gn * bn
imagen_ = nuevaImagen(gn)
imagen_ = binario(imagen_)
imagen_ = deteccionDeElipse(g, umbral, gx, gy, imagen_)
############################--( TKINTER )--#######################################################################################################################################################################
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()
##################################################################################################################################################################################################################
main()

1 comentarios: