- El primer paso fue sacar sacar los bordes de los objetos con el filtro laplaciano
- Después se binariza:
- Se hace un recorrido BFS por cada contorno de la figura y se guarda figura por figura.
- Ahora se saca el gradiente de cada pixel de contorno con la formula siguiente para no hacerlo de toda la imagen y no se tarde tanto:
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 gradiente_sobel(punto, imagen): | |
#print punto | |
pixeles = imagen.load() | |
x = punto[0] | |
y = punto[1] | |
#print x, y | |
z1 = pixeles[x-1, y-1][0] | |
z2 = pixeles[x, y-1][0] | |
z3 = pixeles[x+1, y-1][0] | |
z4 = pixeles[x-1, y][0] | |
z5 = pixeles[x, y][0] | |
z6 = pixeles[x+1, y][0] | |
z7 = pixeles[x-1, y+1][0] | |
z8 = pixeles[x, y+1][0] | |
z9 = pixeles[x+1, y+1][0] | |
Gx = ((z3)+(2*z6)+z9)-((z1)+(2*z4)+(z7)) | |
Gy = ((z7)+(2*z8)+z9)-((z1)+(2*z2)+(z3)) | |
G = sqrt((Gx**2)+(Gy**2)) | |
angulo = atan2(Gy, Gx) | |
angulo = angulo -(pi/2) | |
angulo = float("%.2f" % angulo) | |
return x,y, angulo |
- Después que se tienen todos los angulo se comienzan a agrupar los que tienen ángulos iguales para obtener las líneas que son continuas:
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
for i in contornos: | |
dic = defaultdict(list) | |
for punto in i: | |
x,y,angulo= gradiente_sobel(punto, imagen) | |
dic[angulo].append((x,y)) | |
listas.append(dic) | |
for i in listas: | |
print "*************************************" | |
for j in i: | |
r = int(random.random()*250) | |
g = int(random.random()*250) | |
b = int(random.random()*250) | |
color = (r,g,b) | |
print j | |
print color | |
for k in i[j]: | |
print k | |
nueva.putpixel((k[0], k[1]), color) | |
nueva.save("ss.png") |
Sin embargo mi filtro no detecta muy bien los angulos de algunas lineas continuas hay un problema, que no puede detectar todas las lineas.
Este es el código completo:
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 Tkinter import * | |
from PIL import Image, ImageTk | |
import math | |
import sys | |
import filtros | |
import random | |
import ImageFont, ImageDraw | |
import Image | |
from math import sqrt, atan2, pi, atan | |
from collections import defaultdict | |
DEBUG = True | |
#DEBUG = False | |
def gradiente_sobel(punto, imagen): | |
#print punto | |
pixeles = imagen.load() | |
x = punto[0] | |
y = punto[1] | |
#print x, y | |
z1 = pixeles[x-1, y-1][0] | |
z2 = pixeles[x, y-1][0] | |
z3 = pixeles[x+1, y-1][0] | |
z4 = pixeles[x-1, y][0] | |
z5 = pixeles[x, y][0] | |
z6 = pixeles[x+1, y][0] | |
z7 = pixeles[x-1, y+1][0] | |
z8 = pixeles[x, y+1][0] | |
z9 = pixeles[x+1, y+1][0] | |
Gx = ((z3)+(2*z6)+z9)-((z1)+(2*z4)+(z7)) | |
Gy = ((z7)+(2*z8)+z9)-((z1)+(2*z2)+(z3)) | |
G = sqrt((Gx**2)+(Gy**2)) | |
angulo = atan2(Gy, Gx) | |
angulo = angulo -(pi/2) | |
angulo = float("%.4f" % angulo) | |
return x,y, angulo | |
def bfs(imagen, origen, color): | |
"""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 | |
""" | |
c = [] | |
cola = [] | |
cont = 0 | |
masa = [] | |
pixeles = imagen.load() | |
alto, ancho = imagen.size | |
cola.append(origen) | |
original = pixeles[origen] | |
edges = [] | |
while len(cola) > 0: | |
(x, y) = cola.pop(0) | |
actual = pixeles[x, y] | |
if actual == original or actual == color: | |
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: | |
pixeles[pix_x, pix_y] = color | |
masa.append((pix_x,pix_y)) | |
imagen.putpixel((pix_x, pix_y), color) | |
cont += 1 | |
cola.append((pix_x, pix_y)) | |
c.append((pix_x, pix_y)) | |
imagen.save('prueba', 'png') | |
return imagen, cont, masa, c | |
def encuentra_figuras(imagen): | |
"""encuentra cada objeto y guarda en una lista | |
los bordes de cada objeto | |
""" | |
alto, ancho = imagen.size | |
pixeles = imagen.load() | |
colores = [] | |
cen = [] | |
porcentaje = [] | |
contornos = [] | |
for i in range(alto): | |
for j in range(ancho): | |
if pixeles[i,j] == (255,255,255): | |
r = int(random.random()*250) | |
g = int(random.random()*250) | |
b = int(random.random()*250) | |
nuevo_color = (r,g,b) | |
imagen, cont, masa, c = bfs(imagen, (i,j), nuevo_color) | |
contornos.append(c) | |
total_x = 0 | |
total_y = 0 | |
por = (float(cont)/float(alto*ancho))*100 | |
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) | |
cen.append((x_centro, y_centro)) | |
#draw.ellipse((x_centro+1, y_centro+1, x_centro-1, y_centro-1), fill=(255,0,255)) | |
colores.append([nuevo_color,(x_centro, y_centro), por]) | |
porcentaje.append(por) | |
pixeles = imagen.load() | |
masa = [] | |
#figura_mayor = max(porcentaje) | |
#i = porcentaje.index(figura_mayor) | |
#color_mayor = colores[i][0] | |
imagen.save('colores.png', 'png') | |
#aux.save('poligonos.png', 'png') | |
return contornos, cen | |
def main(): | |
"""funcion principal | |
""" | |
try: | |
imagen_path = sys.argv[1] | |
print "Imagen seleccionada %s" %imagen_path | |
imagen = filtros.abrir_imagen(imagen_path) | |
except: | |
print "No seleccionaste una imagen" | |
return | |
imagen = filtros.hacer_gris(imagen) | |
mascara = [[0,1,0],[1,-4,1],[0,1,0]] | |
imagen = filtros.convolucion(imagen, mascara) | |
imagen = filtros.umbral(imagen) | |
contornos, cen = encuentra_figuras(imagen.copy()) | |
if DEBUG: | |
print "Figuras encontradas %s" %len(contornos) | |
else: | |
pass | |
listas = [] | |
nueva = imagen.copy() | |
todos = nueva.load() | |
for i in contornos: | |
dic = defaultdict(list) | |
for punto in i: | |
x,y,angulo= gradiente_sobel(punto, imagen) | |
dic[angulo].append((x,y)) | |
listas.append(dic) | |
for i in listas: | |
print "*************************************" | |
for j in i: | |
r = int(random.random()*250) | |
g = int(random.random()*250) | |
b = int(random.random()*250) | |
color = (r,g,b) | |
print j | |
print color | |
for k in i[j]: | |
print k | |
nueva.putpixel((k[0], k[1]), color) | |
nueva.save("ss.png") | |
f=open("centros.txt","w") | |
for i in cen: | |
f.write('%s,%s\n' %(i[0], i[1])) | |
f.close | |
if __name__ == "__main__": | |
main() |
Para la detección de los elipses los centros los detecte tomando votos como otras veces, pero hay algunos errores en los centros, pero creo que va por buen camino para poder clasificarlos:
Sería mejor probar primero con una figura muy limpia con un sólo polígono. También es importante recordar que este método únicamente funciona con polígonos regulares. Incluir otras cosas en la imagen de entrada naturalmente aumenta mucho el ruido presente. 5 pts.
ResponderEliminar