jueves, 7 de marzo de 2013

Laboratorio 5

Laboratorio 5 - Detección de círculos (radios distintos)

Hola, esta entrada corresponde a la actividad de laboratorio 5 de la materia de Visión computacional y consiste en la detección de círculos (como la tarea 4), pero esta vez con radios distintos para cada círculo.

Bueno, debido a que esta práctica es similar a la tarea 4 de la misma materia solo tuve que realizar unas pocas modificaciones al código que ya había realizado. La implementación consiste en obtener las coordenadas de los bordes para luego determinar los puntos más lejanos (entre cada círculo obviamente); mediante los puntos antes mencionados obtenemos el diámetro de cada círculo, sabiendo de antemano que la mitad de ese diámetro es el radio.

Al conocer el radio, luego repetimos los métodos usados en la práctica anterior para pintar las circunferencias y etiquetar con un ID a cada círculo:

El código que hace todo lo anteriormente explicado es el siguiente:
 

if __name__ =="__main__":
  
    #transformar()
    #filtrada()
    #conv()
    #umbrales()

    #********************************************************************* 

    miImagen = Image.open("meh.jpeg")
    dr = ImageDraw.Draw(miImagen)
    p = miImagen.load()
    x, y = miImagen.size
    
    for i in range(x):
      for j in range(y): 
       #print p[i, j]  
       #time.sleep(1)
       if p[i,j] == (255,255,255):
        #print "afserfsefr"
        n, bordes = bfs(miImagen, (i,j), (255,0,0))
        menor, mayor, radio = Diametro(bordes)
        print "menor: ", menor[0], " + mayor: ", mayor[0]
        inicio(miImagen, radio)

    miImagen.show()    


def Diametro(bordes):
 menor = min(bordes)
 mayor = max(bordes)
 diametro = mayor[0] - menor[0]
 radio = int(ceil(diametro / 2.0))
 print radio
 return menor, mayor, radio 


def inicio(im, radio): #Ahora es variable
    #im = Image.open("meh4.png")
    mx = [[-1, -1, -1], [2, 2, 2], [-1, -1, -1]]
    my = [[-1, 2, -1], [-1, 2, -1], [-1, 2, -1]]
    imx = convolucion(im, mx)
    imy = convolucion(im, my)
     
    frecuencia = centros(imx, imy, im, radio)
     
    maximo = 0
    suma = 0.0
    for i in frecuencia.keys():
      suma += frecuencia[i]
      if frecuencia[i] > maximo:
          maximo = frecuencia[i] 
    promedio = suma/len(frecuencia)
    umbral = maximo-promedio

    for i in frecuencia.keys():
       if frecuencia[i] < umbral:
           frecuencia.pop(i)
  
    circulos(im,frecuencia,radio)


El pintado de circunferencia así como la etiqueta de los círculos ya lo habíamos visto y lo pueden encontrar en la entrada anterior.

Esto fue lo "nuevo" para esta entrada,  tuve bastantes problemas con bfs para obtener las coordenadas requeridas.

Uno de los intentos fallidos:



La idea es buena pero  la actividad no la pude terminar por falta de tiempo. Intentaré corregirlo y completarlo lo más pronto posible.

Cualquier duda o aclaración pueden dejarla en comentarios.

Saludos a todos!

martes, 5 de marzo de 2013

Tarea 4

Tarea 4 - Detección de círculos

Hola, esta entrada corresponde a la tarea 4 de la clase de visión computacional. La tarea 4 consiste en encontrar círculos en una determinada imagen, lo primero que se hizo fue encontrar los centros de los círculos, luego pintar la circunferencia de cada uno de ellos con distintas tonalidades (de amarillo) y etiquetar los círculos. Todo esto con un radio preestablecido por nosotros.

Para realizar esta práctica hice uso de la transformada de Hough para círculos, además de las siguiente ecuaciones (Enlace sobre información referente):


En donde a y b corresponden al centro del círculo, mientras que "x" y  "y" corresponden a puntos de la circunferencia en cierto ángulo. R es el radio preestablecido (en mi caso yo puse 50).

Primeramente obtenemos los centros de los círculos, para hacer esto se calculan los posibles centros, luego se hace uso de las frecuencias, donde las coordenadas que cuentan con el mayor número de frecuencia serán el centro del círculo.

Para identificar los centros despejamos a y b (centro del círculo) de las ecuaciones anteriores quedando las nuevas ecuaciones de la siguiente manera: 


Para obtener los ángulos, se usan los gradientes(x, y) con los que hemos estado trabajando en posts anteriores, obteniéndolos por medio de máscaras de convolución.

Obtención de los ángulos:


Los centros son etiquetados con un ID y cada circunferencia es pintada con una tonalidad de amarillo distinta (como lo exige la actividad).
Los siguientes códigos códigos realizan los procesos antes mencionados (basados en los códigos de clase):

im = Image.open("circle.png")
    mx = [[-1, -1, -1], [2, 2, 2], [-1, -1, -1]]
    my = [[-1, 2, -1], [-1, 2, -1], [-1, 2, -1]]
    imx = convolucion(im, mx)
    imy = convolucion(im, my)
    radio = 50 # Variando para distintos radios de circulo
    
    frecuencia = centros(imx, imy, im, radio)
    
    maximo = 0
    suma = 0.0
    for i in frecuencia.keys():
        suma += frecuencia[i]
        if frecuencia[i] > maximo:
            maximo = frecuencia[i]

    promedio = suma/len(frecuencia)
    umbral = maximo-promedio

    for i in frecuencia.keys():
        if frecuencia[i] < umbral:
            frecuencia.pop(i)
        
    circulos(im,frecuencia,radio)
    im.save('newone.png')

#Localizacion de centros y pintado de la circunferencia
def centros(imx, imy, im, r):
    ancho,alto = im.size
    frec = dict()
    circulos = dict()
    cx = imx.load()
    cy = imy.load()

    for x in range(ancho):
        for y in range(alto):
            (rx,gx,bx) = cx[x,y]
            (ry,gy,by) = cy[x,y]
            
            gx = float(rx+gx+bx)/3
            gy = float(ry+gy+by)/3
            g = sqrt(pow(gx,2) + pow(gy,2))

            if fabs(g) > 0:
                theta = atan2(gy,gx)
                centro = (int( x - r * cos(theta)), int( y - r * sin(theta)))

                if not centro in frec:
                    frec[centro] = 1
                else:
                    frec[centro] += 1
            
    return frec

def circulos(im, frecuencia, r):
    pixeles = im.load()
    fuente = ImageFont.truetype('/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-C.ttf',20)
    imagen = ImageDraw.Draw(im)
    cont = 1
    color = dict()
    aux = 1
    for i in frecuencia.keys():
        color[i] = (random.randint(250,255), random.randint(100,255), random.randint(0,50)) #Distintos tonos de amarillo, para cada cirunferencia
        imagen.ellipse((i[0]-aux, i[1]-aux, i[0]+aux, i[1]+aux), fill=(0,255,0))
        imagen.text((i[0]+aux+3, i[1]), ('ID: '+str(cont)), fill=(0,0,255), font=fuente)
        cont +=1

    for c in color.keys():
        i ,j = c
        for angulo in range(360): #Pintar
            x = i + r*cos(angulo)
            y = j + r*sin(angulo)
            pixeles[x,y] = color[c] 
    return im


Resultados obtenidos:
En este excluyó al color aqua :(



Fuentes de ayuda:
 

Cualquier duda o aclaración pueden dejarla en comentarios.

Saludos a todos!