Social Icons

twitterfacebookgoogle plusemail

lunes, 15 de abril de 2013

Tarea 5: Detección de elipses

En esta tarea se trabajo para hacer la detección de elipses, aunque realmente se tuvieron unos problemas en el procedimiento. Los pasos principales que se realizaron fueron los siguientes:

  1. Hacer detección de borde.
  2. Elegir pares antiparalelos.
  3. Generar votos a tomando como frontera el borde y las rectas de pares antiparalelos.
  4. Determinar a partir de porcentaje de votos sí realmente es un elipse (Por agregar).
Lo primero es necesario para saber en que area vamos a trabajar, después de saber el area en la que trabajamos, se empiezan a tomar pares de puntos aleatorios para luego sacar su punto medio y tomarlo como voto. A partir del porcentaje de votos se podrá determinar sí es un elipse.

Ahora lo que se implementó, tuve grandes problemas donde dichos problemas eran de herencia de tareas anteriores con los indices en donde estaban en algunos invertidos en otros no. En fin lo que se implementaron solamente fue la realización de los votos y la creación de las rectas antiparalelas con puntos aleatorios seleccionados. Esto fue lo que obtuve.

 


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()

2 comentarios:

  1. Viendo tus rectas es obvio que algo aritmético va mal. Mejor dibuja el segmento para un sólo par de puntos para ver qué está mal (orientación, selección del par, algo de índices, etc.) 3 pts.

    ResponderEliminar