Para comenzar a trabajar con la detección de líneas, primero que nada hay que saber realizar binarización y aplicación de máscaras de convolución. Ambos los pueden encontrar en esta liga
Cuando utilicé una imagen en escala de grsises me generó mucho ruido al final, con líneas muy gruesas y algunas muy desfasadas, el binarizar la imagen me trajo mejores resultados
Detección de líneas
Para detectar líneas en una imagen se utiliza la transformada de Hough; el procedimiento consiste en calcular los gradientes horizontal y vertical de la imagen utilizando máscaras de convolución, en base a estos gradientes calcular el ángulo (θ) de los pixeles de la imagen.En este caso los gradientes vertical y horizontal son dos imágenes cuyos pixeles son las matrices a tratar, dichos pixeles solo tienen valores binarios, es decir blanco o negro (0 o 255).
Una vez teniendo los gradientes se pasa a calcular el ángulo de cada pixel. Con la imagen binarizada se utiliza la siguiente fórmula:
θ=arctan(gy/gx)
También se toman en cuenta los siguientes aspectos que obtuve al correr múltiples veces el programa y observar los distintos ángulos:
- Cuando gx = 0 ygy = 0,θ = nulo, esto es que el ángulo no va en ninguna dirección
- Cuando
gx = 255 ygy = 0,θ = 0 - Cuando
gx = 0 y
gy = 255,θ = 90
Cuando se han calculado los ángulos se calcula una variable ρ (rho) utilizando la siguiente fórmula:
ρ=xcos(θ)+ysin(θ)
Esta ρ se guarda en una lista junto con su respectivo ángulo θ
Después de esto lo que sigue es contar el número de veces que se repite o frecuencia de cada par (ρ,θ). En este caso utilicé un diccionario, estas frecuencias nos permiten determinar que pixeles son líneas ya que cuando un par tiene más repeticiones quiere decir que es más probable que ese par pertenezca a una línea.
Ya como paso final solo es cuestión de pintar cada pixel, yo uyilicé un color verde para las líneas verticales y uno rojo para las líneas horizontales.
El código completo lo pueden encontrar en mi git: github.com/JonathanAlvarado/VisionComputacional/blob/master/lineas.py
La parte más importante es la siguiente y cualquier duda pueden consultar el código completo. Cabe aclarar que tomé como base el código visto en clase de la Dra. Elisa
Código
def convolucion(im,g): w, h = im.size pixeles = im.load() imCon = Image.new('RGB', (w,h)) pixCon = imCon.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 pixCon[x,y] = (suma,suma,suma) return imCon 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(original,im,umbral): '''Transformada de Hough umbral = lineas a considerar''' 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 = original.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] = (0,255,0) elif theta == 90: pixeles [x,y] = (0,0,255) original.save('lineas.png')
Me da duda el fabs adentro del atan... Bastante bien anyhow; 4 pts.
ReplyDelete