jueves, 2 de mayo de 2013

Detección de polígonos




  • 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:
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
view raw gistfile1.py hosted with ❤ by GitHub



  • 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:
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")
view raw gistfile1.py hosted with ❤ by GitHub


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:


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


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:

1 comentario:

  1. 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