Visión Computacional
Tarea 4
Tarea 4
Mi código es el mismo código que se vio en clase, solo que adaptándolo a la estructura que había estado llevando en las tareas anteriores, e incluyendo la parte para dibujar círculos encima de la imagen con ImageDraw. Pero aún tengo algunos problemas para detectar correctamente el círculo teniendo el radio definido dentro del código.
El problema puede estar en que el radio que ingreso manualmente en el código no es el correcto y por eso el programa se confunde, o que al momento de escalar la imagen para adaptarla a la ventana esta provoque que se desfacen los círculos de sus centros reales.
Les dejo las capturas de los intentos que realicé, y como pueden ver un problema más es que suele detectar centros de círculos donde no debería, pero la solución ahí podría ser cambiar la forma en que se suman los votos para los posibles centros y diferenciarlo de los centros detectados con mucho más votos que los demás.
Código
Este es el código actualizado, donde logré la detección de los círculos con radio conocido. Para poder lograrlo tuve que crear una rutina que crea los círculos por separado, y además cambié las máscaras para obtener el gradiente.
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
def draw_some_circles(self, radius_list, image): | |
newdraw = ImageDraw.Draw(image) | |
max_w, max_h = get_image_size(image) | |
for radius in radius_list: | |
x = random.randint(radius, max_w-radius) | |
y = random.randint(radius, max_h-radius) | |
newdraw.ellipse((x-radius, y-radius, x+radius, y+radius), fill=(0, 0, 255)) | |
print 'Drawed circle at center (%d, %d) and radius %d' % (x, y, radius) | |
return image | |
def draw_circles_found(self, image, circles_found): | |
draw = ImageDraw.Draw(image) | |
for i in range(len(circles_found)): | |
x = circles_found[i][0] | |
y = circles_found[i][1] | |
r = circles_found[i][2] | |
draw.ellipse((x-r, y-r, x+r, y+r), fill=None, outline=(255, 0, 0)) | |
draw.text((x, y), 'Circle '+str(i), fill='black') | |
return image | |
def search_circles(self, image, Gx, Gy): | |
width, height = get_image_size(image) | |
pixels_x = Gx.load() | |
pixels_y = Gy.load() | |
radius = 40 | |
votes = list() | |
for i in xrange(height): | |
votes.append([0] * width) | |
for ym in xrange(height): | |
y = height / 2- ym | |
for xm in xrange(width): | |
x = xm - width / 2 | |
gx = pixels_x[ym, xm][0] | |
gy = pixels_y[ym, xm][0] | |
g = math.sqrt(gx ** 2 + gy ** 2) | |
if math.fabs(g) > 0: | |
cosTheta = gx / g | |
sinTheta = gy / g | |
xc = int(round(x - radius * cosTheta)) | |
yc = int(round(y - radius * sinTheta)) | |
xcm = xc + width / 2 | |
ycm = height / 2 - yc | |
if xcm >= 0 and xcm < width and ycm >= 0 and ycm < height: | |
votes[ycm][xcm] += 1 | |
for try_range in xrange(1, 40): | |
added = True | |
while added: | |
added = False | |
for y in xrange(height): | |
for x in xrange(width): | |
v = votes[y][x] | |
if v > 0: | |
for dx in xrange(-20, 20): | |
for dy in xrange(-20, 20): | |
if not (dx == 0 and dy == 0): | |
if y + dy >= 0 and y + dy < height and x + dx >= 0 and x + dx < width: | |
w = votes[y + dy][x + dx] | |
if w > 0: | |
if v - try_range >= w: | |
votes[y][x] = v + w | |
votes[y + dy][x + dx] = 0 | |
added = True | |
maximum = 0 | |
total = 0.0 | |
for x in xrange(width): | |
for y in xrange(height): | |
v = votes[y][x] | |
total += v | |
if v > maximum: | |
maximum = v | |
average = total / (width * height) | |
umbral = (maximum + average) / 2.0 | |
circles_found = list() | |
for x in xrange(width): | |
for y in xrange(height): | |
v = votes[y][x] | |
if v > umbral: | |
circles_found.append((y, x, radius)) | |
print 'Center detected at (%d, %d)' % (y, x) | |
return circles_found | |
def action(self): | |
image = Image.new('RGB', (400, 400), (255, 255, 255)) | |
image = self.draw_some_circles([40, 40, 40, 40], image) | |
image = grayscale(image) | |
sobelx = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]] | |
sobely = [[1, 2, 1], [0, 0, 0], [-1, -2, -1]] | |
Gx = self.convolution(sobelx, image) | |
Gy = self.convolution(sobely, image) | |
circles_found = self.search_circles(image, Gx, Gy) | |
image = self.draw_circles_found(image, circles_found) | |
self.update_image(image) |
Así es la salida obtenida al correr el programa, sin la necesidad de algún parámetro adicional.
Referencias:
http://elisa.dyndns-web.com/~elisa/teaching/comp/vision/circulo.py
Falta que subas el código que me mostraste. El ruido se puede deber a varios aspectos: transformadas erróneas o faltantes de coordenadas, umbral mal elegido para separar borde de fondo o mal mecanismo de aglomeración de votos. 3 pts.
ResponderEliminar