martes, 23 de abril de 2013

Detección de agujeros

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:

#!/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()
view raw gistfile1.py hosted with ❤ by GitHub


Referencias

Elisa Schaeffer

1 comentario: