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.
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.
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
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() |
El borde es descontinuo, y por eso se escapa el BFS. 4 pts.
ResponderEliminar