Laboratorio de Visión Computacional
Actividad 5
Actividad 5
En la entrada de la clase para la detección de círculos con radio definido tuve algunos problemas al encontrar los centros de los círculos para después dibujarlos, pero encontré que usando las máscaras para determinar el gradiente que se vieron en clase fueron las que ayudaron a reconocer bien donde estaban los centros, ya que las máscaras que anteriormente estaba utilizando no eran muy buenas.
También el haber hecho por separado las imágenes con círculos empeoraba mucho la determinación del radio, ya que no solían ser exactos, y esto lo arregle haciendo una rutina en el mismo programa que crea una imagen con círculos de diferentes radios, y después esta imagen entra en la rutina de la detección de círculos, por supuesto sin darle como parámetros los radios a la función de detección.
Y en la parte de la detección de círculos para que no tardara tanto en la búsqueda de posibles centros puse un rango de tamaños corto, normalmente hace lo mismo si lo dejo buscando en rangos desde 1 hasta la altura de la imagen, pero por ahorrar tiempo al hacer las pruebas utilice un rango definido.
Aquí vemos como resultan las imágenes después de aplicar las nuevas máscaras.
La imagen original para una de las pruebas fue:
Y el resultado de la detección:
Enseguida el original y resultado de algunas pruebas.
No es muy preciso al encontrar los radios de los círculos, pero detecta bien los centros en su mayoría.
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
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() | |
votes = list() | |
for i in xrange(height): | |
votes.append([0] * width) | |
posible_radius = list() | |
for i in xrange(height): | |
posible_radius.append([0] * width) | |
for radius in range(20, 70, 10): | |
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 | |
posible_radius[xcm][ycm] = radius | |
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: | |
radius = posible_radius[x][y] | |
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([20, 30, 25, 45, 50], 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) |
Cada que el programa es ejecutado en terminal podemos ver la impresión de las posiciones aleatorias donde los círculos son creados, y después la impresión de donde encontró el programa que son los centros encontrados.
Bastante decente, 8 pts.
ResponderEliminar