Ahora se debe agregar a lo que se tiene (aún sin andar googleando y sin usar librerías para visión) una rutina que detecta todos los agujeros en la imagen, con las siguientes características:
- Los agujeros detectadas se marcan con un borde morado oscuro y un relleno de morado claro.
- Un tono ligeramente diferente en cada agujero.
- Se marca el centro de cada agujero con un punto amarillo.
- Al centro de cada agujero se agrega una etiqueta del ID del agujero.
- El programa imprime un listado que indica para cada ID el tamaño del agujero (como porcentajes del tamaño de la imagen).
Estas son las imágenes que yo conseguí tomando fotos en mi casa y los resultados de lo que obtuve:
Ejemplo 1:
![]() |
Original |
![]() |
Histograma que ayuda a encontrar los cruces |
![]() |
Ayuda a saber los píxeles del contorno |
![]() |
Agujero detectado, centro: amarillo, id: 0, relleno: morado claro, contorno: morado obscuro |
Ejemplo 2:
Ejemplo 3:
Y esta última es una imagen de internet
Ejemplo 4 :
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
#!/usr/bin/python | |
from PIL import Image, ImageDraw | |
import random | |
import filtros | |
import time | |
from math import sqrt, fabs | |
import sys | |
import matplotlib.pyplot as plt | |
import numpy as np | |
def bfs(imagen, origen, color, color_obs, contorno,original_im): | |
"""colorea todo el objeto recibe como parametros el | |
nuevo color con el que se pinta,la coordenada de inicio y | |
la imagen, y regresa un arreglo con la masa y la imagen | |
""" | |
elegido = 0 | |
c = [] | |
cola = [] | |
cont = 0 | |
masa = [] | |
pixeles = imagen.load() | |
alto, ancho = imagen.size | |
cola.append(origen) | |
original = pixeles[origen] | |
edges = [] | |
p_o = original_im.load() | |
while len(cola) > 0: | |
(x, y) = cola.pop(0) | |
actual = pixeles[x, y] | |
if actual == original or actual == color or actual == color_obs: | |
for dx in [-1, 0, 1]: | |
for dy in [-1, 0, 1]: | |
candidato = (x + dx, y + dy) | |
pix_x = candidato[0] | |
pix_y = candidato[1] | |
if pix_x >= 0 and pix_x < alto and pix_y >= 0 and pix_y < ancho: | |
contenido = pixeles[pix_x, pix_y] | |
if contenido == original or contenido == (0,0,0): | |
if (pix_x, pix_y) in contorno: | |
elegido = color_obs | |
else: | |
elegido = color | |
pixeles[pix_x, pix_y] = elegido | |
p_o[pix_x, pix_y] = elegido | |
masa.append((pix_x,pix_y)) | |
imagen.putpixel((pix_x, pix_y), elegido) | |
original_im.putpixel((pix_x, pix_y), elegido) | |
cont += 1 | |
cola.append((pix_x, pix_y)) | |
c.append((pix_x, pix_y)) | |
imagen.save('prueba', 'png') | |
return imagen, cont, masa, original_im | |
def contornos(im): | |
"""devuelve una lista con las pisiciones donde | |
hay contornos | |
""" | |
mascara = [[0,1,0],[1,-4,1],[0,1,0]] | |
lap = filtros.convolucion(im, mascara) | |
lap.save("lap.png") | |
pixeles_con = lap.load() | |
contornos = [] | |
for i in range(im.size[0]): | |
for j in range(im.size[1]): | |
if pixeles_con[i,j][0] == 255: | |
contornos.append((i,j)) | |
return contornos | |
def encuentra_huecos(im,original, col, ren): | |
"""se encuentran las intersecciones y se enumeran | |
los huecos | |
""" | |
pixeles = im.load() | |
contorno = contornos(im) | |
area_total = float(im.size[0]*im.size[1]) | |
huecos = [] | |
c = 0 | |
draw = ImageDraw.Draw(original) | |
for i in col: | |
for j in ren: | |
if pixeles[j,i][0] == 0: | |
#para los colores claros de morado | |
r_1 = random.randint(150,230) | |
g_1 = random.randint(100,230) | |
b_1 = random.randint(160, 255) | |
color_claro = (r_1,g_1,b_1) | |
#para los colores obscuros de morado | |
r_2 = random.randint(120,230) | |
g_2 = random.randint(0,100) | |
b_2 = random.randint(108, 255) | |
color_obs = (r_2,g_2,b_2) | |
im, cont, masa,original = bfs(im,(j,i),color_claro, color_obs, contorno,original) | |
total_x = 0 | |
total_y = 0 | |
for l in range(len(masa)): | |
total_x = total_x + masa[l][0] | |
total_y = total_y + masa[l][1] | |
x_centro = total_x/len(masa) | |
y_centro = total_y/len(masa) | |
huecos.append((cont,j,i,x_centro,y_centro)) | |
c = c + 1 | |
draw = ImageDraw.Draw(original) | |
for i, car in enumerate(huecos): | |
print "Hueco con ID %s" %i | |
print "Area de %s%%\n" %str((int(car[0])*100)/area_total) | |
draw.ellipse((car[3]-2, car[4]-2, car[3]+2, car[4]+2), | |
fill="yellow") | |
draw.text((car[3], car[4]), str(i), fill=(0,0,0)) | |
original.show() | |
def dibuja_lineas(lista, imagen, op): | |
"""dibuja las lineas verdes si es horizontal | |
o rojo si es vertical | |
""" | |
x, y = imagen.size | |
draw = ImageDraw.Draw(imagen) | |
if op == 1: | |
for i in lista: | |
#lineas horizontales | |
draw.line((0,i, x,i), fill="green") | |
pass | |
else: | |
for i in lista: | |
#lineas verticales | |
draw.line((i,0, i,y), fill="red") | |
pass | |
return imagen | |
def encuentra_minimos(lista): | |
"""encuentra los minimos de la grafica | |
""" | |
c = 0 | |
promedio = 0 | |
minimos_temp = {} | |
minimos = {} | |
for i, valor in enumerate(lista): | |
try: | |
if lista[i-10]>=lista[i] and lista[i+10]>=lista[i]: | |
minimos_temp[i]=lista[i] | |
c = c + 1 | |
promedio = promedio + valor | |
except: | |
pass | |
promedio = promedio/c | |
minimos_temp = sorted(minimos_temp.items(), key=lambda x: x[1]) | |
for i in minimos_temp: | |
if i[1] < promedio: | |
minimos[i[0]] = i[1] | |
return minimos | |
def graficar(columnas, renglones): | |
"""grafica dividiendo el canvas en 2 | |
columnas y renglones | |
""" | |
fig = plt.figure() | |
fig.subplots_adjust(hspace=.5) | |
uno = fig.add_subplot(2,1,1) | |
uno.plot(np.arange(len(renglones)), renglones) | |
uno.set_xlabel('renglon') | |
uno.set_ylabel('suma') | |
uno.set_title('Horizontal') | |
uno.grid(True) | |
dos = fig.add_subplot(2,1,2) | |
dos.plot(np.arange(len(columnas)), columnas, 'r') | |
dos.set_xlabel('columna') | |
dos.set_ylabel('suma') | |
dos.set_title('Vertical') | |
dos.grid(True) | |
plt.savefig('hola.png') | |
def vertical(pixeles,x,y): | |
"""sumatoria por columnas | |
""" | |
col_total = [] | |
for i in range(y): | |
col = [] | |
for j in range(x): | |
col.append(pixeles[j,i][0]) | |
col = sum(col) | |
col_total.append(col) | |
return col_total | |
def horizontal(pixeles,x,y): | |
"""sumatoria por renglones | |
""" | |
row_total = [] | |
for i in range(x): | |
row = [] | |
for j in range(y): | |
row.append(pixeles[i,j][0]) | |
row = sum(row) | |
row_total.append(row) | |
return row_total | |
def main(): | |
"""funcion principal | |
""" | |
try: | |
imagen_path = sys.argv[1] | |
imagen = filtros.abrir_imagen(imagen_path) | |
except: | |
print "No seleccionaste una imagen" | |
return | |
imagen = filtros.hacer_gris(imagen) | |
imagen = filtros.normalizar(imagen) | |
original = imagen.copy() | |
imagen = filtros.umbral(imagen) | |
bina = imagen.copy() | |
#imagen.show() | |
pixeles = imagen.load() | |
x, y = imagen.size | |
suma_columnas = vertical(pixeles,x,y) | |
suma_renglones = horizontal(pixeles,x,y) | |
#se encuentran los minimos de las columnas | |
min_col = encuentra_minimos(suma_columnas) | |
#se encuentran los minimos de los renglones | |
min_ren = encuentra_minimos(suma_renglones) | |
#se dibujan las lineas verticales | |
nueva = dibuja_lineas(min_col, original, 1) | |
#se dibujan las lineas horizontales | |
nueva = dibuja_lineas(min_ren, nueva, 2) | |
#nueva.show() | |
graficar(suma_columnas, suma_renglones) | |
encuentra_huecos(bina, original, min_col, min_ren) | |
main() |
Referencias
Elisa Schaeffer
Muy bien; 5 pts.
ResponderEliminar