Created
April 18, 2013 04:04
-
-
Save cecyurbina/5410028 to your computer and use it in GitHub Desktop.
This file contains hidden or 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, 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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment