jueves, 18 de abril de 2013

Relleno de elipses/círculos


  • Identifica cada elipse/círculo individual




  • Rellénalo de un color aleatorio
  • Sigue marcando su centro con bolita & ID con etiqueta



  • Imprime un listado de los áreas de los círculos/elipses en porcentaje de la imagen completa
Elipses detectados rellenos

Con el porcentaje de área calculada
Diferenciando círculos de elipses


Encuentra círculos y elipses




Encuentra círculos y elipses

Código completo:

#!/usr/bin/python
from PIL import Image, ImageDraw
import random
import filtros
import time
from math import sqrt, fabs, atan2, pi, cos, sin, ceil, degrees
import sys
import numpy
def dibuja_elipse(num,imagen):
"""dibuja elipses aleatorios para la imagen inicial
"""
draw = ImageDraw.Draw(imagen)
x_imagen, y_imagen = imagen.size
rangox = 20*2
rangoy = 50*2
for i in range(num):
ancho = random.randint(rangox, rangoy)
largo = random.randint(rangox, rangoy)
x = random.randint(ancho, x_imagen-(ancho))
y = random.randint(largo, y_imagen-(largo))
if random.choice('ab') == 'b':
draw.ellipse((x,y, x+ancho,y+largo),fill="black")
else:
draw.ellipse((x,y, x+ancho,y+ancho),fill="black")
return imagen
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
"""
print type(origen)
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 = []
porcentaje = []
elipses = []
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)
elipses.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)
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')
return imagen, colores, elipses
def puntos(elipses, ptos):
"""puntos aleatorios del contorno de cada
figura
"""
puntos_linea = []
for elipse in elipses:
punto1 = random.choice(elipse)
punto2 = random.choice(elipse)
ptos.append(punto1)
ptos.append(punto2)
puntos_linea.append((punto1, punto2))
return puntos_linea, ptos
def crea_imagen(ancho, largo):
"""crea una imagen con cierta dim, en blanco
"""
im = Image.new('RGB', (ancho,largo), (255,255,255))
return im
def gradiente_sobel(punto, pixeles):
#print punto
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)
#print G, angulo
return x,y, angulo
def alarga_linea(pendiente,x0, y0, matriz, im, Px, Py):
"""alarga el punto hasta que se termina el objeto relleno
"""
draw = ImageDraw.Draw(im)
pixeles = im.load()
cont = 1
while True:
if Px > x0:
x = x0 - 1
else:
x = x0 + 1
y = (pendiente*(x - x0)) + y0
x0 = x
y0 = y
y = int(y)
#print "la y es %s" %y
matriz[x,y] = matriz[x,y] + 1
try:
#draw.ellipse((x-4, y-4,x-1,y-1), fill="blue")
#print pixeles[x, y][0], cont
if pixeles[x, y][0] == 255:
break
except:
pass
cont = cont + 1
return matriz, im
def dibuja_ec_elipse(temp, centro, maxi, mini):
"""dibuja el elipse deacuerdo al los puntos
centro y maximos y minimos encontrados con su ecuacion
"""
puntos = []
draw = ImageDraw.Draw(temp)
a = 0.0
color = (random.randint(175,255), random.randint(114, 196), 0)
while True:
x = centro[0]+(mini*cos(a))
y = centro[1]+(maxi*sin(a))
puntos.append((x,y))
draw.ellipse((x-1, y-1, x+1,y+1), fill=color)
a = a + .01
if a > 2*pi:
break
return temp, puntos, color
def encuentra_puntos(im, elipses, matriz, ptos):
"""Encuentra el punto medio de los dos punto aleatorios, asi como
el punto de interseccion y la pendiente
"""
puntos_linea, ptos = puntos(elipses, ptos)
pixeles = im.load()
lineas = []
largo_linea = 60
draw = ImageDraw.Draw(im)
for punto_linea in puntos_linea:
s = []
k = []
for punto in punto_linea:
x,y,angulo = gradiente_sobel(punto, pixeles)
x1 = x - largo_linea*cos(angulo)
y1 = y - largo_linea*sin(angulo)
x2 = x + largo_linea*cos(angulo)
y2 = y + largo_linea*sin(angulo)
linea = x1, y1, x2, y2
draw.line((x1,y1, x2, y2),fill="red")
draw.ellipse((x-3, y-3, x+3,y+3), fill="green")
s.append([x1,y1,x2,y2,x,y])
x1, x2, x3, x4 = s[0][0], s[0][2], s[1][0], s[1][2]
y1, y2, y3, y4 = s[0][1], s[0][3], s[1][1], s[1][3]
Px_num = (x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4)
Px_den = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)
Py_num = (x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4)
Py_den = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)
ym = (s[0][5]+s[1][5])/2
xm = (s[0][4]+s[1][4])/2
try:
Px = Px_num/Px_den
Py = Py_num/Py_den
#print "La interseccion esta en %s, %s" %(Px, Py)
draw.ellipse((Px-3, Py-3, Px+3,Py+3), fill="blue")
draw.ellipse((xm-2, ym-2, xm+2,ym+2), fill="yellow")
draw.line((xm,ym, Px, Py),fill="red")
pendiente = (Py-ym)/(Px-xm)
#print "Pendiente %s" %pendiente
matriz, im = alarga_linea(pendiente,xm, ym, matriz, im, Px, Py)
except Exception, e:
#print str(e)
pass
return matriz, im, ptos
def main():
"""funcion principal
"""
num = 2
largo = 500
ancho = 700
im = crea_imagen(ancho, largo)
x, y = im.size
area_total = largo*ancho
diagonal = sqrt((x-0)**2 + (y-0)**2)
im = dibuja_elipse(num,im)
temp = im.copy()
im.save("original.png")
im = filtros.hacer_gris(im)
mascara = [[0,1,0],[1,-4,1],[0,1,0]]
lap = filtros.convolucion(im, mascara)
lap.save("lap.png")
c = 0
cir = 0
im1, colores, elipses =encuentra_figuras(lap)
#matriz = [[0 for i in range(y)] for j in range(x)]
for figura in elipses:
matriz_1 = numpy.zeros(x*y).reshape((x,y))
#print matriz_1
tem = []
dic = {}
tem.append(figura)
ptos = []
for i in range(1000):
matriz_1, im, ptos = encuentra_puntos(im, tem, matriz_1, ptos)
i,j = numpy.unravel_index(matriz_1.argmax(), matriz_1.shape)
draw = ImageDraw.Draw(temp)
#draw.ellipse((i-5, j-5, i+5,j+5), fill="blue")
for pto in ptos:
x_0 = pto[0]
y_0 = pto[1]
distancia = sqrt((x_0-i)**2 + (y_0-j)**2)
dic[pto] = distancia
key1,value = max(dic.iteritems(), key=lambda x:x[1])
#draw.ellipse((key1[0]-5, key1[1]-5, key1[0]+5,key1[1]+5), fill="red")
deltay = j-key1[1]
deltax = i-key1[0]
angulo1 = abs(degrees(atan2(deltay, deltax))-180)
key2,value = min(dic.iteritems(), key=lambda x:x[1])
#draw.ellipse((key2[0]-5, key2[1]-5, key2[0]+5,key2[1]+5), fill="red")
deltay = j-key2[1]
deltax = i-key2[0]
angulo2 = abs(degrees(atan2(deltay, deltax))-180)
diagonal_elipse = sqrt((key1[0]-key2[0])**2 + (key1[1]-key2[1])**2)
p = (diagonal_elipse*100)/diagonal
print "*****************************************************"
if dic[key1] != dic[key2]:
c = c + 1
print "Elipse #%s" %c
else:
print "Circulo #%s" %cir
cir = cir + 1
print "Centro en (%s, %s)" %(i, j)
print "Radio maximo es de %s con angulo de %s" %(dic[key1], angulo1)
print "Radio minimo es de %s con angulo de %s" %(dic[key2], angulo2)
print "Porcentaje diagonal %s" %p
centro = (int(i), int(j))
maxi = dic[key1]
mini = dic[key2]
if (maxi >= 315 and maxi <= 45) or (maxi >= 135 and maxi <= 225):
a = mini
b = maxi
else:
a = maxi
b = mini
temp, puntos, col = dibuja_ec_elipse(temp, centro, a, b)
l=0
for s in puntos:
if s in ptos:
l = l + 1
if l > 5:
print "si es elipse"
temp.show()
r = int(random.random()*250)
g = int(random.random()*250)
b = int(random.random()*250)
nuevo_color = (r,g,b)
#print centro
imagen, cont, masa, k, area_eli = bfs2(temp, centro, nuevo_color, col)
print area_eli
print area_total
p = float((area_eli*100))/area_total
print "Porcentaje area %s" %p
print "*****************************************************"
dib = ImageDraw.Draw(imagen)
dib.ellipse((i-5, j-5, i+5,j+5), fill="blue")
dib.text(centro, str(c), fill=(255,255,255))
imagen.show()
main()
view raw gistfile1.py hosted with ❤ by GitHub


Repositorio

1 comentario: