jueves, 28 de febrero de 2013

Laboratorio 4

Laboratorio 4 - Detección de diagonales

Hola, esta entrada corresponde a la cuarta actividad del laboratorio de visión computacional. La actividad consiste en localizar y pintar las diagonales de los objetos de una imagen.
En esta misma entrada primero hablaré sobre la detección de lineas horizontales y verticales (esto fue la tarea 4 de la misma materia) continuar con el seguimiento y explicar de donde viene la detección de lineas en diagonal.

Detección de líneas 

Para la detección de lineas usamos la transformada de Hough, lo que realizamos fue hacer el cálculo de los gradientes vertical y horizontal de la imagen usando máscaras de convolución (como lo hicimos en la actividad de detección de bordes) seguido de obtener los gradiente antes mencionados,  continuamos calculando los valores de theta de los pixeles de la imagen.

Cuando tenemos los gradientes, calculamos el ángulo de cada pixel, yo usé una imagen binarizada sin filtro, porque cuando la pasaba por mi filtro tendía a poner demasiadas lineas verticales y horizontales.
Bueno, obtuvimos los ángulo de los pixeles con la siguiente fórmula:


Las variables de esta fórmula son arctan (arcotangente), gy (gradiente y), gx (gradiente x).
Después de calcular los ángulos, se calcula la variable rho usando al fórmula siguiente:


El valor de rho es guardado en una lista con el valor del ángulo theta.

Seguido de esto obtuvimos las frecuencias de cada "theta, rho" usando un diccionario, esto con el fin de determinar qué pixeles son lineas, tomando en cuenta que cuando un par (theta, rho) tiene más repeticiones, quiere decir que hay más probabilidad de que el par sea una línea (mismo ángulo.)

Para terminar pintamos pixeles pertenecientes a las líneas (azules para horizontales, rojo para verticales y verde para las líneas diagonales)

Para las líneas diagonales solo agregué una condición que cuando el ángulo no fuera ni 0 ni 90 ni 180 ni 270 lo tomara como una diagonal (y lo pinté de verde).
A continuación los highlights del código:
'''
Convolucion y deteccion de lineas
'''

def convolucion(im,g):
 w, h = im.size
 pixeles = im.load()
 imConvolucion = Image.new('RGB', (w,h))
 pix = imConvolucion.load()
 
     for x in range(w):
         for y in range(h):
          suma = 0
              for i in range(x-1, x+2):
                  for j in range(y-1, y+2):
                       try:
                           suma += g[i - (x-1)][j - (y-1)] * pixeles[i,j][1]
                       except:
                           pass
              pix[x,y] = (suma,suma,suma)
     return imConvolucion
 
def frecuentes(histo, cantidad):
 frec = list()
 for valor in histo:
  if valor is None:
       continue
  
  frecuencia = histo[valor]
  acepta = False
  if len(frec) <= cantidad:
   acepta = True
  if not acepta:
   for (v, f) in frec:
    if frecuencia > f:
               acepta = True
               break
  if acepta:
   frec.append((valor, frecuencia))
   frec = sorted(frec, key = lambda tupla: tupla[1])
   if len(frec) > cantidad:
           frec.pop(0)
     incluidos = list()
     for (valor, frecuencia) in frec:
         incluidos.append(valor)
 
     return incluidos
 
def deteccionDeLineas():
    umbral = 10
    im = Image.open("meh3.jpg")

    sobelx = [[-1, -1, -1], [2, 2, 2], [-1, -1, -1]]
    sobely = [[-1, 2, -1], [-1, 2, -1], [-1, 2, -1]]
    imx = convolucion(im, sobelx)
    imy = convolucion(im, sobely)
    gx = imx.load()
    gy = imy.load()
    w,h = im.size
    comb = {}
    pixeles = im.load()
    resultado = list()
 
    for x in range(w):
        datos = list()
        for y in range(h):
            hor = gx[x,y][0]
            ver = gy[x,y][0]
 
            if fabs(hor) + fabs(ver) <= 0.0:#nada en ninguna direccion                                                                        
                theta = None
            elif hor == 0 and ver == 255:
                theta = 90
            elif fabs(hor) > 0.0:
                theta = atan(fabs(ver/hor))
            if theta is not None:
                rho = fabs( x * cos(theta) + y * sin(theta))
 
                if x > 0 and x < w-1 and y > 0 and y < h-1:
                    if (rho, theta) in comb:
       comb[ (rho, theta) ] += 1
                    else:
                        comb[ (rho, theta) ] = 1
                datos.append( (rho, theta) )
            else:
                datos.append((None,None))
        resultado.append(datos)
 
    incluir = int(ceil (len(comb) * umbral))
 
    frec = frecuentes(comb, incluir)
 
    for x in range(w):
     for y in range(h):
            if x > 0 and x< w-1 and y > 0 and y < h-1:
    rho, theta = resultado[x][y]
 
   if (rho, theta) in frec:
                    if theta == 0:
                        pixeles[x,y] = (255,0,0)
                    elif theta == 90:
                        pixeles [x,y] = (0,0,255)
              elif theta != 0 and theta != 90 and theta != 180 and theta != 270: #Para diagonales
                    pixeles [x, y] = (0,255,0) #Los pintamos verde
                          print "Soy un pixel diagonal"
    im.save('meh5.jpg')



Ahora algunos resultados con imágenes sencillas (hacer click sobre ellas para ampliarlas):






(Para diagonales)



(Una sección se pinto verde porque traia letras XD)




Mi liga de git: https://github.com/eddypre/VisionTriana

Cualquier duda o aclaración pueden dejarla en comentarios. 

Saludos a todos!


1 comentario: