domingo, 14 de abril de 2013

Tarea 5: Detección de elipses

Para esta tarea se nos piden los siguientes puntos:

  • Detectar elipses marcados con tonos naranja.
  • Marcar el centro con un punto azul
  • Poner una etiqueta ID 
  • Imprimir un listado de los semidiametros perpendiculares y su porcentaje con la diagonal máxima de la imagen

Para realizar esto, se nos pide utilizar el método de la cuerda tangente, es por eso que se hacen los siguientes pasos:
  1. Cambiar a grises
  2. Sacar convolución Laplaciana para sacar bordes
  3. Normalizo la imagen
  4. Binarizo los datos
  5. Sacamos el promedio
  6. Se agrega un umbral
  7. Agregamos BFS para detectar todos los bordes 
  8. Los pintamos de diferentes colores
  9. Sacamos mascara de sobel en X
  10. Sacamos mascara de sobel en Y
  11. Generamos puntos aleatorios para cada borde detectado
  12. Calculamos su theta 
  13. Creamos dos lineas tangenciales a los bordes
  14. Se calcula su punto medio
  15. Realizamos los votos a partir de esa linea hasta al final del borde siguiente
  16. Repetimos varias veces para obtener mejor precisión en el centro
  17. Se calcula los radios en X y en Y
  18. dibujamos un punto entre 0 a 360 grados a partir de los datos obtenidos
  19. Vemos el elipse detectado en un tono anaranjado
Les muestro unas capturas de pantalla del procedimiento








Otros ejemplos:








Este es el código de la función principal, si quieren ver mi repositorio, ahí se encuentra completo.



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")
#Aplica BFS a los bordes detectados
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 aplica mascara sobel en X y Y
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 los elipses
dibuja = ImageDraw.Draw(imagen_BFS)
x, y = imagen_BFS.size
puntos = numpy.zeros(x*y).reshape((x, y))
centros = []
#Para cada borde detectado sacamos puntos aleatorios para hacer votos en la linea donde posiblemente tenemos un centro
for elipse in elipses:
x, y = imagen_BFS.size
puntos = numpy.zeros(x*y).reshape((x, y))
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
#Calculamos theta segun mascara de sobel
if abs(gx_1) + abs(gy_1) <= 0:
theta = None
else:
theta = atan2(gy_1, gx_1)
l = 50
#Creamos las lineas tangentes
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)
#Misma operacion con otro punto
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:
#Detectamos la interseccion y pendiente
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
#Empezamos a hacer votos hasta encontrar un borde
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
#De los resultados sacamos los mas voteados
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))
#Sacamos los radios
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
#Dibujamos elipse
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)
porcentaje = float(Rx * 100)/float(x)
print "ID: %s SemiDiametro: %s Porcentaje: %s" % (i, Rx, porcentaje)
color = (randint(175,255), randint(134, 196), 0) #rango anaranjado
a = 0
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)
#Ponemos imagen en ventana
poner_imagen(imagen_BFS)
#Etiquetamos
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)
dibuja.ellipse((centros[i][0]-2, centros[i][1]-2, centros[i][0]+2, centros[i][1]+2), fill="blue")
#Guardamos
imagen_BFS.save("paso_lineas.jpg")
#Tiempo
fin = time.time()
tiempo = fin - inicio
print "Tiempo que trascurrio -> " + str(tiempo)
return tiempo
view raw python.py hosted with ❤ by GitHub

1 comentario: