Loading [MathJax]/extensions/TeX/AMSsymbols.js

9 de mayo de 2013

Actividad 9: Detección de Esquinas

Laboratorio de Visión Computacional
Actividad 9

Para la entrega de esta semana se nos pidió detectar esquinas en polígonos y hacer un "wire-frame" del mismo sobre la imagen. Utilizamos la técnica llamada Filtro Mediano, el cual es muy fácil de implementar, y este detecta esquinas de polígonos sin importar si son regulares o irregulares. El único problema se presenta cuando las esquinas de los polígonos son la unión de dos aristas con un ángulo interno muy grande.

Los pasos que se siguieron para esta tarea fueron los siguientes:
  • Aplicar filtro de escala de grises a la imagen.
  • Aplicar el filtro mediano para encontrar las esquinas.
  • Aplicar el filtro de binarización para resaltar estas esquinas.
  • Identificar las coordenadas de los puntos donde se encontraron las esquinas.
  • Detectar bordes en la imagen original.
  • Hacer un pequeño corte donde comienza una de las esquinas.
  • Usar BFS para seguir el camino del borde de la figura y marcar que puntos se unen con cuáles.
  • De lo anterior se obtienen los puntos pertenecientes a las esquinas de cada figura.
  • Y por último se dibujan círculos sobre estos puntos y líneas que los unen.

Pruebas


Imagen original e imagen con detección de bordes.


Detección de esquinas.


Esquinas y líneas.


Código


Enseguida los fragmentos de código relevantes. Si se quiere ver el código completo, pueden encontrarlo en el siguiente repositorio.


def bfs(self, image, start_pixel_pos, color):
pixels = image.load()
width, height = get_image_size(image)
queue = []
copy = []
count = 0
queue.append(start_pixel_pos)
original = pixels[start_pixel_pos]
while 0 < len(queue):
(x, y) = queue.pop(0)
current = pixels[x, y]
if current == original or current == color:
for pos_x in [-1, 0, 1]:
for pos_y in [-1, 0, 1]:
pixel_x = x + pos_x
pixel_y = y + pos_y
if pixel_x >= 0 and pixel_x < width and pixel_y >= 0 and pixel_y < height:
pixel_data = pixels[pixel_x, pixel_y]
if pixel_data == original:
pixels[pixel_x, pixel_y] = color
queue.append((pixel_x, pixel_y))
copy.append((pixel_x, pixel_y))
count += 1
return image, count, copy
def detect_forms(self, image):
pixels = image.load()
width, height = get_image_size(image)
percentages = []
all_colors = []
polygons = []
for i in range(width):
for j in range(height):
if pixels[i, j] == (255, 255, 255):
r = random.randint(100, 255)
g = random.randint(100, 255)
b = random.randint(100, 255)
image, count, copy = self.bfs(image, (i, j), (r, g, b))
per = float(count)/float(width * height)
percentages.append(per)
all_colors.append((r, g, b))
pixels = image.load()
polygons.append(copy)
return polygons, image
def median_filter(self, image):
width, height = get_image_size(image)
image = grayscale(image)
pixels = image.load()
newimage = image
result = newimage.load()
for x in range(width):
for y in range(height):
neighborhood = list()
for pos_x in [-1, 0, 1]:
for pos_y in [-1, 0, 1]:
if pos_x != 0 or pos_y != 0:
pixel_x = x + pos_x
pixel_y = y + pos_y
if pixel_x >= 0 and pixel_x < width and pixel_y >= 0 and pixel_y < height:
neighborhood.append(pixels[pixel_x, pixel_y][0])
n = int(len(neighborhood)/2)
neighborhood.sort()
median = (neighborhood[n] + neighborhood[n-1])/2
result[x, y] = (median, median, median)
return newimage
def find_corners(self, original_image, image):
corners = Image.new('RGB', (SIZE, SIZE), (255, 255, 255))
width, height = get_image_size(corners)
pixels = corners.load()
oim = original_image.load()
im = image.load()
for i in range(width):
for j in range(height):
color = abs(oim[i, j][0] - im[i, j][0])
pixels[i, j] = (color, color, color)
corners = binarization(corners, 100)
return corners
def draw_wires_detected(self, image, wires_frames):
draw = ImageDraw.Draw(image)
counter = 1
for wire_frame in wires_frames:
print 'Polygon', counter
r = random.randint(100, 255)
g = random.randint(100, 255)
b = random.randint(100, 255)
for corner in wire_frame:
x, y = corner
draw.ellipse((x-3, y-3, x+3, y+3), fill=(r, g, b))
counter += 1
return image
def action(self):
original_image = Image.new('RGB', (SIZE, SIZE), (255, 255, 255))
image = Image.new('RGB', (SIZE, SIZE), (255, 255, 255))
#create_polygons = [(20,20,20,100,100,100,100,20), (120,120,120,180,180,180,180,120)]
create_polygons = [(20,20,20,100,100,100,100,20), (120,120,120,180,180,180,180,120), (160,20,190,20,190,50,160,50)]
#create_polygons = [(70, 20, 40, 90, 80, 160, 160, 120, 180, 40)]
#create_polygons = [(100, 30, 160, 70, 160, 120, 100, 160, 40, 120, 40, 70)]
original_image = self.draw_some_polygons(create_polygons, original_image)
original_image = grayscale(original_image)
image = self.draw_some_polygons(create_polygons, image)
image = grayscale(image)
image = self.median_filter(image)
corners_image = self.find_corners(original_image, image)
corners_points, trash = self.detect_forms(corners_image)
h = [[0, 1, 0], [1, -4, 1], [0, 1, 0]]
original_image = average_allneighbors(original_image)
original_image = binarization(original_image, 200)
edges = self.convolution(h, original_image)
polygons, image_bfs = self.detect_forms(edges)
wires_frames = self.search_wires_frames(polygons, corners_points)
output_image = self.draw_wires_detected(image_bfs, wires_frames)
self.update_image(output_image)
view raw corners.py hosted with ❤ by GitHub

Y por último otro ejemplo más.




Referencias:
Elisa Schaeffer, "Detección de polígonos y esquinas", 2013 [En línea]. Disponible en: http://elisa.dyndns-web.com/~elisa/teaching/comp/vision/poligonos.pdf

1 comentario:

Nota: solo los miembros de este blog pueden publicar comentarios.