lunes, 4 de marzo de 2013

Visión Computacional: Detección de Circulos



En esta entrada realizaremos lo que es la detección de circulos.


Los circulos seran del mismo radio el cual se dara como argumento desde la terminal.

Para poder encontrar los circulos primero necesitamos encontrar lo que son los centros de cada uno de ellos y esto lo encontramos teniendo xc, yx.

Para poder calcularlos debemos de tener cosas que se realizaron en las entradas anteriores como lo que es convolución ya que necesitamos lo que es obtener la magnitud del gradiente.

Primero calculamos lo que la magnitud:



Después obtenemos lo siguiente:




Teniendo lo anterior calculamos:



Recuerden que r es el radio que le damos al correr el programa, teniendo ya todo lo anterior se calcula el posible centro de un circulo.

Lo primero que intente fue poner los centros y realmente no los sacaba bien:





Los centros lo puse que me los marcara de color rojo pero en este caso en vez de detectarme 6 centros solo me detecto 3 y fuera del rango donde deberian de estar.

Después trate de agregarle lo demas y el codigo ya no me jalo :(, no logre terminarlo

Código:
from Tkinter import *
import Image, ImageTk
from sys import argv
from time import *
import numpy
from math import floor, fabs
import math
class Aplicacion(Frame):
def __init__(self,parent):
Frame.__init__(self,parent)
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title('Ventana')
self.pack(fill=BOTH, expand=1)
self.o_imagen=argv[1]
imagen = self.obtener_imagen()
self.cargar_imagen(imagen)
self.conv = Button(text='Convolucion', command =self.boton_convolucion).pack(side=LEFT)
self.conv = Button(text='Circulos', command =self.boton_circulos).pack(side=LEFT)
def boton_convolucion(self):
image = self.filtro()
ima=image.save('filtrada.jpg')
img2 = self.mascara(image)
id = img2.save('mascara.png')
# img=self.normalizar(img)
#img2 = img.save('normalizada.png')
#img = self.binarizar(img)
#im=img.save('binarizada.png')
img = self.cargar_imagen(img2)
print 'sale de vonvolucion'
return img2
def boton_circulos(self):
image=Image.open(self.o_imagen)
self.radio=int(argv[3])
img=self.boton_convolucion() #self.conv
image=self.circulos(img)
def circulos(self,img):
print 'entra circulos'
ancho,alto=img.size
votos=numpy.empty((ancho, alto))
pixels=img.load()
for i in range(ancho):
y=ancho/2-i
for j in range(alto):
x = j-alto/2
p=self.mxy[i,j]
if fabs(p) > 0:
costheta=(float(self.gx[i,j]/p))
sentheta=(float(self.gy[i,j]/p))
# print type(self.radio)
#raw_input()
xc = int(round(x - self.radio * costheta))
yc = int(round(y - self.radio * sentheta))
xcm=xc+alto/2
ycm = ancho/2-yc
if xcm >= 0 and xcm < alto and ycm >= 0 and ycm < ancho:
votos[xc][yc] += 1
votos=self.votes(ancho,alto,votos)
maximo = 0
suma = 0.0
for x in xrange(ancho):
for y in xrange(alto):
v = votos[x][y]
suma += v
if v > maximo:
maximo = v
promedio = suma / (ancho * alto)
umbral = (maximo + promedio) / 2.0
coordenadas = []
for x in xrange(ancho):
for y in xrange(alto):
v = votos[x][y]
if v > umbral:
coordenadass.append((x,y))
draw = ImageDraw.Draw(img)
colores=[]
c=0
for o,p in coordenadas:
pixels[o,p]=(0,255,0)
draw.text((o,p), '%s'%s(c+1),(0,0,0))
rg=random.randint(0,255)
c +=1
draw.ellipse((o-self.radio,p-self.radio,o+self.radio,p+self.radio),outline=(rg,rg,0))
img.save('eeeeeeeeeeeeeeeeeeeee.png')
print 'sale circulos'
return
def votes(self,ancho,alto,votos):
dim = max(ancho, alto)
for rango in range(1,int(round(dim*0.1))):
agregado = True
while agregado:
agregado=False
for y in range(ancho):
for x in range(alto):
v = votos[y][x]
if v>0:
for dx in range(-rango,rango):
for dy in range(-rango,rango):
if y+dy >=0 and y+dy<ancho and x + dx >= 0 and x + dx < alto:
w = votos[y+dy][x+dx]
if w>0:
if v - rango >= w:
votos[y][x]=v+w
votos[y+dy][x+dx]=0
agregado = True
return votos
def filtro(self):
inicio = time()
image = self.escala_grises()
pixels = image.load()
ancho, alto =image.size
lista = [-1,0,1]
for i in range(ancho):
for j in range(alto):
promedio = self.vecindad(i,j,lista,self.matriz)
pixels[i,j] = (promedio,promedio,promedio)
fin = time()
tiempo_t = fin - inicio
print "Tiempo que tardo en ejecutarse filtro = "+str(tiempo_t)+" segundos"
return image
def escala_grises(self):
inicio = time()
image = Image.open(self.o_imagen)
pixels = image.load()
ancho,alto = image.size
self.matriz = numpy.empty((ancho, alto))
for i in range(ancho):
for j in range(alto):
(r,g,b) = image.getpixel((i,j))
escala = (r+g+b)/3
pixels[i,j] = (escala,escala,escala)
self.matriz[i,j] = int(escala)
fin = time()
tiempo_t = fin - inicio
print "Tiempo que tardo en ejecutarse escala de grises = "+str(tiempo_t)+" segundos"
df = image.save('escala.png')
return image
def vecindad(self,i,j,lista,matriz):
promedio = 0
indice = 0
for x in lista:
for y in lista:
a = i+x
b = j+y
try:
if self.matriz[a,b] and (x!=a and y!=b):
promedio += self.matriz[a,b]
indice +=1
except IndexError:
pass
try:
promedio=int(promedio/indice)
return promedio
except ZeroDivisionError:
return 0
def mascara(self,image):
inicio = time()
#Mascara Sobel
sobelx = ([-1,0,1],[-2,0,2],[-1,0,1]) #gradiente horizontal
sobely = ([1,2,1],[0,0,0],[-1,-2,-1]) # gradiente vertical
img=self.convolucion(sobelx,sobely,image)
fin=time()
tiempo_t = fin - inicio
print "Tiempo que tardo en ejecutarse convolucion = "+str(tiempo_t)+" segundos"
return img
def convolucion(self,h1,h2,image):
pixels = image.load()
ancho,alto = image.size
#Parte circulo
self.gx=numpy.empty((ancho, alto))
self.gy=numpy.empty((ancho, alto))
self.mxy=numpy.empty((ancho, alto))
self.votos=numpy.empty((ancho, alto))
print 'votos',self.votos
#FIn Parte Circulo
for e in range(ancho):
for t in range(alto):
self.votos[e,t]=0
a=len(h1[0])
self.conv = numpy.empty((ancho, alto))
#self.
self.minimo = 255
self.maximo = 0
for x in range(ancho):
for y in range(alto):
#self.votos[x,y]=0
sumax = 0.0
sumay = 0.0
for i in range(a):
for j in range(a):
try:
sumax +=(pixels[x+i,y+j][0]*h1[i][j])
sumay +=(pixels[x+i,y+j][0]*h2[i][j])
except:
pass
gradiente = math.sqrt(pow(sumax,2)+pow(sumay,2))
self.conv[x,y]=gradiente
gradiente = int(gradiente)
pixels[x,y] = (gradiente,gradiente,gradiente)
p = gradiente
self.gx[x,y]=sumax
self.gy[x,y]=sumay
self.mxy[x,y]=p
if p < self.minimo:
self.minimo = p
if p > self.maximo:
self.maximo = p
print 'botos',self.votos
#print 'datos',self.datos
return image
main()
view raw s.py hosted with ❤ by GitHub



1 comentario:

  1. Incluye en la entrada solamente el código relevante y el resto va en el Git con liga en el blog. Fíjate bien en la notación matemática y en los acentos de las palabras. Intenta ser más modular (no metas mugrero dentro del método convolución) y no copies ciegamente partes de mi código ejemplo sin pensar o preguntar por su propósito. 2 pts por el avance parcial.

    ResponderEliminar