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.
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:
Después trate de agregarle lo demas y el codigo ya no me jalo :(, no logre terminarlo
Código:
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
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() |
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