Mi repositorio de los códigos. Liga.
Primero que nada, sacamos el gradiente de tal forma que podamos analizar la imagen.
Para luego, procesarlo de manera que tengamos su información relevante de cada pixel, para sacar los valores más significativos y los pintamos de manera que un color el centro y a partir del centro calculado dibujar con el radio dado, el circulo, para este caso, utilicé diferentes tonalidades de amarillo para cada circulo al igual que pongo en el centro, para la imagen guardada, un punto verde y múltiples círculos para remarcar su contorno, este es el código.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def boton_circulo(): | |
inicio = time.time() | |
label.destroy() | |
radio = 100 | |
max = 0 | |
suma = 0.0 | |
#A grises | |
imagen = cambiar_agrises(path_imagen_original) | |
imagen.save("paso_1.jpg") | |
votos = list() | |
h_hori = numpy.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) | |
h_verti = numpy.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]]) | |
imagen_hori = convolucion(imagen, numpy.multiply(1.0/1.0,h_verti)) | |
imagen_hori.save("paso_2.jpg") | |
imagen_verti = convolucion(imagen, numpy.multiply(1.0/1.0,h_hori)) | |
imagen_verti.save("paso_3.jpg") | |
#Obtener votos | |
pixeles_hori = imagen_hori.load() | |
pixeles_verti = imagen_verti.load() | |
dim_x, dim_y = imagen.size | |
votos = [] | |
for pos in range(dim_x): | |
votos.append([0] * dim_x) | |
for y_m in range(dim_x): | |
y = dim_y / 2 - y_m | |
for x_m in range(dim_x): | |
x = x_m - dim_x / 2 | |
gra_y = pixeles_hori[y_m, x_m][0] | |
gra_x = pixeles_verti[y_m, x_m][0] | |
gra = sqrt(gra_x ** 2 + gra_y ** 2) | |
if fabs(gra) > 0: | |
x_c = int(round(x - radio * (gra_x/gra))) | |
y_c = int(round(y - radio * (gra_y/gra))) | |
x_c_m = x_c + dim_x /2 | |
y_c_m = dim_y / 2 - y_c | |
if y_c_m >= 0 and x_c_m < dim_x and y_c_m < dim_y and x_c_m >= 0: | |
votos[y_c_m][x_c_m] = votos[y_c_m][x_c_m] + 1 | |
for rango in range(1, int(round(dim_x * 0.1))): | |
agrega = True | |
while agrega: | |
agrega = False | |
for y in range(dim_y): | |
for x in range(dim_x): | |
v = votos[y][x] | |
if v > 0: | |
for dx in range(-rango, rango): | |
for dy in range(-rango, rango): | |
if not (dx == 0 and dy == 0): | |
if y + dy < dim_x and y + dy >= 0 and x + dx >= 0 and x + dx < dim_x: | |
w = votos[y + dy][x + dx] | |
if w > 0: | |
if v - rango >= w: | |
votos[y][x] = v + w | |
votos[y + dy][x + dx] = 0 | |
agrega = True | |
print 'Dimx = %d, Dimy = %d' % (dim_x, dim_y) | |
for x in range(dim_x): | |
for y in range(dim_y): | |
v = votos[y][x] | |
suma += v | |
if v > max: | |
max = v | |
prom = suma / (dim_x * dim_y) | |
umbral = (max + prom) / 2.0 | |
centros = [] | |
for x in range(dim_x): | |
for y in range(dim_y): | |
v = votos[y][x] | |
if v > umbral: | |
print 'Centro en %d, %d. ' % (y,x) | |
centros.append((y,x)) | |
dibuja = ImageDraw.Draw(imagen) | |
dim_x, dim_y = imagen.size | |
for conta in range(len(centros)): | |
x = centros[conta][0] | |
y = centros[conta][1] | |
tono = randint(128,255) | |
dibuja.ellipse((x-radio, y-radio, x+radio, y+radio), fill=None, outline=(tono, tono, 0)) | |
radio = radio + 1 | |
dibuja.ellipse((x-radio, y-radio, x+radio, y+radio), fill=None, outline=(tono, tono, 0)) | |
radio = radio - 1 | |
dibuja.ellipse((x-radio, y-radio, x+radio, y+radio), fill=None, outline=(tono, tono, 0)) | |
radio = radio - 2 | |
dibuja.ellipse((x-radio, y-radio, x+radio, y+radio), fill=None, outline=(tono, tono, 0)) | |
radio = radio + 2 | |
dibuja.ellipse((x-radio, y-radio, x+radio, y+radio), fill=None, outline=(tono, tono, 0)) | |
radio = radio - 3 | |
dibuja.ellipse((x-radio, y-radio, x+radio, y+radio), fill=None, outline=(tono, tono, 0)) | |
radio = radio + 3 | |
dibuja.ellipse((x-radio, y-radio, x+radio, y+radio), fill=None, outline=(tono, tono, 0)) | |
dibuja.ellipse((x-2, y-2, x+2, y+2), fill="green") | |
imagen.save("Resultado.png") | |
poner_imagen(imagen) | |
global frame | |
barra = frame.winfo_height() | |
for conta in range(len(centros)): | |
x = centros[conta][0] | |
y = centros[conta][1] | |
label_fig = Label(text = str(conta)) | |
label_fig.place(x=x,y=y+barra) | |
#Tiempo | |
fin = time.time() | |
tiempo = fin - inicio | |
print "Tiempo que trascurrio -> " + str(tiempo) | |
return tiempo |
Estas son algunas capturas de pantalla, los resultados que nos dio por medio de las imágenes guardadas con el punto verde en el centro y por otra parte las capturas de la ventana en donde pongo sus etiquetas del ID de cada circulo.
Es importante decir, yo empecé a utilizar otras máscaras para sacar los gradientes en 0 y 90 grados, pero al momento de hacerlo los círculos quedaban muy mal ubicados y computacionalmente tardaba más, esto es porque por ejemplo al usar Prewitt quedaban los gradientes bien definidos pero no en los grados dados, por lo que al utilizar Sobel, es mucho mas rápido al utilizar solo ceros y unos, y computacionalmente menos pesado, solo un poco.
Bien, pero el código pudiese ser modularizado. 5 pts.
ResponderEliminar