miércoles, 17 de abril de 2013

Lab: Relleno de elipses/círculos

Se nos pide que del código que detecte elipses y/o círculos

• Identificar cada elipse/círculo individual
• Rellénalo de un color aleatorio
• Sigue marcando su centro con bolita & ID con etiqueta
• Imprime un listado de los áreas de los círculos/elipses
• En porcentaje de la imagen completa

Por lo que para realizar esto, utilicé las mismas funciones que he estado reutilizando durante el curso, para identificar el elipse o círculo lo que se hace es verificar sus radios y comparar que si el radio calculado obtenido es igual para ambos lados (o sea, vertical y horizontal) quiere decir que tenemos un círculo, por el contrario tenemos un elipse.

Estos se rellenan con mi subrutina BFS con un color aleatorio, se marca una bolita en el centro y se identifican para proceder a obtener un listado de los que son círculos y elipses, al igual que su porcentaje en base a la figura completa.

Estas son las capturas del programa.





En donde podemos ver que el programa sabe satisfactoriamente si es un circulo o un elipse al igual que información en base a la imagen en general

A continuación expongo el código modificado.
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
view raw lab.py hosted with ❤ by GitHub

1 comentario: