def BFS(imagen, inicio, color):
    #Busqueda de anchura para determinar una figura
    pixeles = imagen.load()
    altura, ancho = imagen.size
    
    fila, columna = inicio
    original = pixeles[fila, columna]
    
    cola = []
    cola.append((fila, columna))
    masa = []
    c = []
    
    while len(cola) > 0:
        (fila, columna) = cola.pop(0)
        actual = pixeles[fila, columna]
        if actual == original or actual == color:
            for dx in [-1, 0, 1]:
                for dy in [-1, 0, 1]:
                    candidato = (fila + dy, columna + dx)
                    if candidato[0] >= 0 and candidato[0] < altura and candidato[1] >= 0 and candidato[1] < ancho:
                        contenido = pixeles[candidato[0], candidato[1]]
                        if contenido == original:
                            pixeles[candidato[0], candidato[1]] = color
                            imagen.putpixel((candidato[0], candidato[1]), color)
                            cola.append(candidato)
                            masa.append((candidato[0], candidato[1]))
                            c.append((candidato[0], candidato[1]))
    
    return imagen, masa, c

def aplicar_BFS(imagen_BFS):
    #aplica busqueda de anchura a todas las figuras encontradas con color aleatorio
    pixeles = imagen_BFS.load()
    x, y = imagen_BFS.size
    colores = []
    elipses = []
    for a in range(x):
        for b in range(y):
            if pixeles[a, b] == (255, 255, 255):
                color = (random.randint(0,255), random.randint(0,255), random.randint(0, 255))
                imagen_BFS, masa, c = BFS(imagen_BFS.convert("RGB"), (a, b), color)
                elipses.append(c)
                x_suma = 0
                y_suma = 0
                for i in range(len(masa)):
                    x_suma = x_suma + masa[i][0]
                    y_suma = y_suma + masa[i][1]
                
                x_centro = x_suma/len(masa)
                y_centro = y_suma/len(masa)
                colores.append([color, 0, (x_centro, y_centro)])
                pixeles = imagen_BFS.load()
                masa = []
    
    #suma la cantidad de colores diferentes en la imagen
    pixeles = imagen_BFS.load()
    for a in range(x):
        for b in range(y):
            for n in range(len(colores)):
                if colores[n][0] == pixeles[a,b]:
                    colores[n][1] = colores[n][1] + 1
    
    print colores
    
    suma = 0
    for i in range(len(colores)):
        suma = suma + colores[i][1]
    
    global frame
    y = frame.winfo_height()
    
    #Obtenemos porcentajes
    prom = []
    for i in range(len(colores)):
        promedio = float(colores[i][1])/float(suma)*100.0
        if promedio > 3.0:
            print "Porcentajes: "
            print "Figura " + str(i) + ": " + str(promedio)
            prom.append((i, promedio, colores[i][0]))

    maxim = 0.0
    for i in range(len(prom)):
        if maxim < prom[i][1]:
            maxim = prom[i][1]
            fig = prom[i][0]
            color_max = prom[i][2]

    #Itentificamos fondo y lo pintamos a gris
    print "Fondo fig: " + str(fig)
    imagen_BFS = pinta_fondo(imagen_BFS, color_max)
    #poner_imagen(imagen_BFS)
    return imagen_BFS, colores, elipses


def pinta_fondo(imagen_BFS, color_max):
    #pintamos fondo de manera que obtenemos el color que predomina en la imagen
    pixeles = imagen_BFS.load()
    x, y = imagen_BFS.size
    for a in range(x):
        for b in range(y):
            if pixeles[a, b] == color_max:
                color = (100,100,100)
                imagen_BFS, masa, c = BFS(imagen_BFS.convert("RGB"), (a, b), color)
                return imagen_BFS

def boton_elipse():
    inicio = time.time()
    label.destroy()
    
    max = 0
    suma = 0.0
    
    #A grises
    imagen = cambiar_agrises(path_imagen_original)
    imagen.save("paso_1.jpg")
    votos = list()
        
    #A grises
    imagen = cambiar_agrises(path_imagen_original)
    imagen.save("paso_1.jpg")
    
    #Agrego Laplaciana
    h_lap = numpy.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])
    imagen_prom, puntos = convolucion(imagen, numpy.multiply(1.0/1.0,h_lap))
    imagen_prom = cambiar_umbral(imagen_prom, 0.5)
    imagen_prom.save("paso_2.jpg")
    
    #Agrego normalizacion
    imagen_nor = normalizacion(imagen_prom)
    imagen_nor.save("paso_3.jpg")
    
    #Agrego umbral para binarizar
    umbral_valor = 0.1
    imagen_bin = cambiar_umbral(imagen_nor.convert("RGB"), umbral_valor)
    imagen_bin.save("paso_4.jpg")
    
    #Pongo promedio
    imagen_prom = cambiar_promedio(imagen_bin.convert("RGB"))
    imagen_prom.save("paso_5.jpg")
    
    #Agrego umbral para binarizar
    umbral_valor = 0.08
    imagen_bin2 = cambiar_umbral(imagen_prom.convert("RGB"), umbral_valor)
    imagen_bin2.save("paso_6.jpg")
    
    #Pongo promedio
    imagen_prom = cambiar_promedio(imagen_bin2.convert("RGB"))
    imagen_prom.save("paso_7.jpg")
    
    #Pongo promedio
    imagen_prom = cambiar_promedio(imagen_prom.convert("RGB"))
    imagen_prom.save("paso_8.jpg")
    
    #Agrego umbral para binarizar
    umbral_valor = 0.5
    imagen_BFS = cambiar_umbral(imagen_prom.convert("RGB"), umbral_valor)
    imagen_BFS.save("paso_9.jpg")
    
    #Se aplica BFS
    imagen_BFS, colores, elipses = aplicar_BFS(imagen_BFS)
    imagen_BFS.save("paso_10.jpg")

    x, y = imagen_BFS.size

    pixeles = imagen_BFS.load()
    bordes_detectados = []

    #Se aplican mascaras de sobel
    h_Y = numpy.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
    h_X = numpy.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]])
    imagen_hori, puntos_GX = convolucion(imagen, numpy.multiply(1.0/1.0,h_X))
    imagen_hori.save("paso_sobelX.jpg")
    pixeles_GX = imagen_hori.load()
    imagen_verti, puntos_GY = convolucion(imagen, numpy.multiply(1.0/1.0,h_Y))
    imagen_verti.save("paso_sobelY.jpg")
    pixeles_GY = imagen_verti.load()
    
    #Empezamos a detectar elipses y circulos
    dibuja = ImageDraw.Draw(imagen_BFS)
    x, y = imagen_BFS.size
    puntos = numpy.zeros(x*y).reshape((x, y))
    centros = []
    for elipse in elipses:
        x, y = imagen_BFS.size
        puntos = numpy.zeros(x*y).reshape((x, y))
        #Sacamos 2000 puntos aleatorios para calcular el centro mas preciso
        for i in range(2000):            
            tam = len(elipse)
            punto_1 = elipse[randint(0,tam-1)]
            punto_2 = elipse[randint(0,tam-1)]
            
            x_1 = punto_1[0]
            y_1 = punto_1[1]
        
            x_2 = punto_2[0]
            y_2 = punto_2[1]
        
            gx_1 = puntos_GX[x_1, y_1]
            gy_1 = puntos_GY[x_1, y_1]
        
            gx_2 = puntos_GX[x_2, y_2]
            gy_2 = puntos_GY[x_2, y_2]
        
            gx_1 = - float(gx_1)
            gx_2 = - float(gx_2)
        
            x_22 = x_2
            y_22 = y_2
            x_11 = x_1
            y_11 = y_1
        
            if abs(gx_1) + abs(gy_1) <= 0:
                theta = None
            else:
                theta = atan2(gy_1, gx_1)

        
            l = 50
                
            if theta is not None:
                theta = theta-(pi/2)
                x_1 = x_11 - l * cos(theta)
                y_1 = y_11 - l * sin(theta)
                x_2 = x_11 + l * cos(theta)
                y_2 = y_11 + l * sin(theta)
            
        
            if abs(gx_2) + abs(gy_2) <= 0:
                theta = None
            else:
                theta = atan2(gy_2, gx_2)
        
    
            if theta is not None:
                theta = theta-(pi/2)
                x_3 = x_22 - l * cos(theta)
                y_3 = y_22 - l * sin(theta)
                x_4 = x_22 + l * cos(theta)
                y_4 = y_22 + l * sin(theta)
                
            y_medio = (y_11+y_22) / 2
            x_medio = (x_11+x_22) / 2
                
            pixeles = imagen_BFS.load()
            
            try:
                Px = ((x_1*y_2-y_1*x_2)*(x_3-x_4)-(x_1-x_2)*(x_3*y_4-y_3*x_4))/((x_1-x_2)*(y_3-y_4)-(y_1-y_2)*(x_3-x_4))
                Py = ((x_1*y_2-y_1*x_2)*(y_3-y_4)-(y_1-y_2)*(x_3*y_4-y_3*x_4))/((x_1-x_2)*(y_3-y_4)-(y_1-y_2)*(x_3-x_4))

                Dx = Px - x_medio
                Dy = Py - y_medio
                m = Dy/Dx 
                x0 = x_medio
                y0 = y_medio
                
                #Obtenemos votos
                while True:
                    x = x0+1
                    y = m*(x-x0)+y0
                    if pixeles[x,y] == (0, 0, 0):
                        puntos[x, y] = puntos[x, y] + 1
                        x0 = x
                        y0 = y
                    else:
                        break
            except:
                pass
        max = numpy.max(puntos)
        index = numpy.where(puntos==max)
        try:
            mayor_x = sum(index[0])/len(index[0])
            mayor_y = sum(index[1])/len(index[0])
            #dibuja.ellipse((mayor_x-2, mayor_y-2, mayor_x+2, mayor_y+2), fill="blue")
            centros.append((mayor_x, mayor_y))
        except:
            mayor_x = index[0]
            mayor_y = index[1]
            #dibuja.ellipse((mayor_x-2, mayor_y-2, mayor_x+2, mayor_y+2), fill="blue")
            centros.append((mayor_x, mayor_y))

    #de los mayores detectados, los utilizamos como centros
    r_x = []
    r_y = []
    pixeles_imagen = imagen_BFS.load()
    for i in range(len(centros)):
        x0 = int(centros[i][0])
        y0 = int(centros[i][1])
        while True:
            y0 = y0 + 1
            if pixeles_imagen[x0, y0] != (0, 0, 0):
                r_y.append((x0, y0))
                break

    for i in range(len(centros)):
        x0 = int(centros[i][0])
        y0 = int(centros[i][1])
        while True:
            x0 = x0 + 1
            if pixeles_imagen[x0, y0] != (0, 0, 0):
                r_x.append((x0, y0))
                break
    Radios = []
    x, y = imagen_BFS.size
    print "Semidiametros perpendiculares del elipse" 
    for i in range(len(centros)):
        x0 = int(centros[i][0])
        y0 = int(centros[i][1])
        x1 = int(r_x[i][0])
        y1 = int(r_x[i][1])
        x2 = int(r_y[i][0])
        y2 = int(r_y[i][1])
        Rx = sqrt((x1-x0)**2+(y1-y0)**2)
        Ry = sqrt((x2-x0)**2+(y2-y0)**2)
        
        #si los radios son iguales, es un circulo
        if Rx == Ry:
            cad = "Es circulo"
        else:
            cad = "Es elipse"
            
        porcentaje = float(Rx * 100)/float(x)
        print "ID: %s  SemiDiametro: %s  Porcentaje: %s    %s" % (i, Rx, porcentaje, cad)
        #Radios.append((Rx, Ry))
        color = (255, 255, 255) 
        a = 0
        #Pintamos en los 360 grados
        while a < 2*pi:
            x4, y4 = x0 + Rx * sin(a), y0 + Ry * cos(a)
            a = a + 0.01
            dibuja.ellipse((x4-2, y4-2, x4+2, y4+2), fill=color)

    for i in range(len(centros)):
        #Agregamos BFS empezando por el centro del circulo o elipse capturado
        color = (random.randint(0,255), random.randint(0,255), random.randint(0, 255))
        imagen_BFS, masa, c = BFS(imagen_BFS.convert("RGB"), (int(centros[i][0]), int(centros[i][1])), color)
        dibuja.ellipse((centros[i][0]-2, centros[i][1]-2, centros[i][0]+2, centros[i][1]+2), fill="blue")

    poner_imagen(imagen_BFS)

    global frame
    y = frame.winfo_height()
    for i in range(len(centros)):
        label_fig = Label(text = str(i))
        label_fig.place(x = centros[i][0],  y = centros[i][1] + y)
        

    imagen_BFS.save("paso_lineas.jpg")
    #Tiempo
    fin = time.time()
    tiempo = fin - inicio
    print "Tiempo que trascurrio -> " + str(tiempo)
    
    return tiempo