domingo, 17 de febrero de 2013

Tarea 2: Identificación de figuras

Para la tarea dos de la materia de Visión Computacional, se nos pide hacer un programa en donde identifiquemos los objetos, al igual que poner etiquetas y detectar el fondo de alguna imagen, por lo que para realizar este programa, utilizo la manera de detectar los bordes como lo hicimos en el laboratorio anterior en donde obtengo la diferencia del promedio y sacar el cambio para poder después binarizar y obtener una imagen con bordes definidos.



Para esta parte de la tarea es agregar primero que nada que los contornos sean definidos y continuos, por lo que estuve trabajando para mejorar mi código anterior y obtener unos mejores contornos, hice varias veces el promedio y la binarización para hacerlos más anchos y así no tener problemas de continuidad.


Ahora después de tener los contornos marcados y continuos, realicé una subrutina que hace una búsqueda en anchura para ir determinando los pixeles vecinos y saber si pertenecen a una figura o no, al momento de ir rellenando las figuras, vamos descartando aquellas que se encuentren con pixeles negros, siendo solamente objetos que van a procesarse para obtener figuras completas y de ahí sacar sus datos importantes.


Luego de obtener las diferentes figuras, calculamos su centro de masa, esto simplemente checando sus coordenadas para después dividirlos entre el total y colocándolos dentro de la ventana.

También detecto el fondo de manera que cambie de color gris, este simplemente calculo el porcentaje de color de cada figura y obtengo el más grande asegurando que es el fondo, para luego proceder en cambiar su color a gris.


Para obtener bordes más definidos, vario los valores de umbral para la binarización, por lo que obtenemos imágenes con bordes resultados y sin tanto ruido, como podemos ver en esta imagen la cual es la misma que la anterior pero con valores umbral diferentes.


Ahora muestro capturas de pantalla de algunas imágenes que verifique.






A continuación muestro el código, en donde las funciones relevantes son BFS, aplicar_BFS, pintar_fondo.

from Tkinter import *
from PIL import Image, ImageTk
from math import floor
import numpy
import random
def ventana():
root = Tk()
root.title('Tarea 2')
global frame
frame = Frame()
frame.pack(padx=5,pady=5)
poner_imagen(obtener_original(path_imagen_original))
b1 = Button(text='Original', command = boton_original).pack(in_=frame, side=LEFT)
b4 = Button(text='Identificar', command = boton_bordes).pack(in_=frame, side=LEFT)
root.mainloop()
def poner_imagen(image):
photo = ImageTk.PhotoImage(image)
global label
label = Label(image=photo)
label.imagen = photo
label.pack()
def BFS(imagen, inicio, color):
#Busqueda de anchura para determinar una figura
pixeles = imagen.load()
altura, ancho = imagen.size
fila, columna = inicio
original = pixeles[fila, columna]
cola = []
cola.append((fila, columna))
masa = []
while len(cola) > 0:
(fila, columna) = cola.pop(0)
actual = pixeles[fila, columna]
if actual == original or actual == color:
for dx in [-1, 0, 1]:
for dy in [-1, 0, 1]:
candidato = (fila + dy, columna + dx)
if candidato[0] >= 0 and candidato[0] < altura and candidato[1] >= 0 and candidato[1] < ancho:
contenido = pixeles[candidato[0], candidato[1]]
if contenido == original:
pixeles[candidato[0], candidato[1]] = color
imagen.putpixel((candidato[0], candidato[1]), color)
cola.append(candidato)
masa.append((candidato[0], candidato[1]))
return imagen, masa
def cambiar_agrises(path_original):
imagen = Image.open(path_imagen_original).convert("RGB")
pixeles = imagen.load()
x, y = imagen.size
imagen_nueva = Image.new("RGB", (x, y))
colores = []
for a in range(x):
for b in range(y):
pixel_color = pixeles[a, b]
promedio = sum(pixel_color)/3
tupla_promedio = (promedio, promedio, promedio)
colores.append(tupla_promedio)
imagen_nueva.putpixel((a, b), tupla_promedio)
return imagen_nueva
def cambiar_promedio(imagen):
pixeles = imagen.load()
x, y = imagen.size
imagen_nueva_prom = Image.new("RGB", (x, y))
colores = []
for a in range(x):
for b in range(y):
pixel_color = pixeles[a, b]
veces = 5
suma = 0
promedio = 0
try:
pixel_norte = pixeles[a-1,b]
except IndexError:
pixel_norte = (0, 0, 0)
veces = veces - 1
try:
pixel_sur = pixeles[a+1, b]
except IndexError:
pixel_sur = (0, 0, 0)
veces = veces - 1
try:
pixel_este = pixeles[a, b+1]
except IndexError:
pixel_este = (0, 0, 0)
veces = veces - 1
try:
pixel_oeste = pixeles[a, b-1]
except IndexError:
pixel_oeste = (0, 0, 0)
veces = veces - 1
Rojos_suma = pixel_norte[0] + pixel_sur[0] + pixel_este[0] + pixel_oeste[0] + pixel_color[0]
Verdes_suma = pixel_norte[1]+ pixel_sur[1] + pixel_este[1] + pixel_oeste[1] + pixel_color[1]
Azul_suma = pixel_norte[2]+ pixel_sur[2] + pixel_este[2] + pixel_oeste[2] + pixel_color[2]
Rojo_prom = Rojos_suma/veces
Verdes_prom = Verdes_suma/veces
Azul_prom = Azul_suma/veces
tupla_promedio = (Rojo_prom, Verdes_prom, Azul_prom)
colores.append(tupla_promedio)
imagen_nueva_prom.putpixel((a, b), tupla_promedio)
return imagen_nueva_prom
def diferencia(imagen):
pixeles = imagen.load()
x, y = imagen.size
imagen_nueva_prom = Image.new("RGB", (x, y))
colores = []
for a in range(x):
for b in range(y):
pixel_color = pixeles[a, b]
veces = 5
suma = 0
promedio = 0
try:
pixel_norte = pixeles[a-1,b]
except IndexError:
pixel_norte = (0, 0, 0)
veces = veces - 1
try:
pixel_sur = pixeles[a+1, b]
except IndexError:
pixel_sur = (0, 0, 0)
veces =veces - 1
try:
pixel_este = pixeles[a, b+1]
except IndexError:
pixel_este = (0, 0, 0)
veces =veces - 1
try:
pixel_oeste = pixeles[a, b-1]
except IndexError:
pixel_oeste = (0, 0, 0)
veces =veces - 1
Rojos_suma = pixel_norte[0] + pixel_sur[0] + pixel_este[0] + pixel_oeste[0] + pixel_color[0]
Verdes_suma = pixel_norte[1]+ pixel_sur[1] + pixel_este[1] + pixel_oeste[1] + pixel_color[1]
Azul_suma = pixel_norte[2]+ pixel_sur[2] + pixel_este[2] + pixel_oeste[2] + pixel_color[2]
Rojo_prom = Rojos_suma/veces
Verde_prom = Verdes_suma/veces
Azul_prom = Azul_suma/veces
Rojo_dif = pixel_color[0] - Rojo_prom
Verde_dif = pixel_color[1] - Verde_prom
Azul_dif = pixel_color[2] - Azul_prom
tupla_promedio = (Rojo_dif, Verde_dif, Azul_dif)
colores.append(tupla_promedio)
imagen_nueva_prom.putpixel((a, b), tupla_promedio)
return imagen_nueva_prom
def normalizacion(imagen):
pixeles = imagen.load()
x, y = imagen.size
min = 0
max = 0
imagen_nueva = Image.new("RGB", (x, y))
for a in range(x):
for b in range(y):
pixel_color = pixeles[a, b]
max_ant = max
max_new = pixel_color[0]
min_ant = min
min_new = pixel_color[0]
if (max_new >= max_ant):
max = max_new
elif (min_new <= min_ant):
min = min_new
elif (min == 0 and max == 255):
break
print min
print max
for a in range(x):
for b in range(y):
pixel_color = pixeles[a, b]
try:
nuevo_pixel = ( float(pixel_color[0]) - float(min) )*( float(255) / (float(max) - float(min)) )
nuevo_pixel = int(floor(nuevo_pixel))
except:
nuevo_pixel = 255
tupla_promedio = (nuevo_pixel, nuevo_pixel, nuevo_pixel)
imagen_nueva.putpixel((a, b), tupla_promedio)
return imagen_nueva
def cambiar_umbral(imagen, umbral_valor):
pixeles = imagen.load()
x, y = imagen.size
imagen_nueva = Image.new("RGB", (x, y))
for a in range(x):
for b in range(y):
pixel_color = pixeles[a, b]
valor_canal = float(pixel_color[0])
color_nor = valor_canal/255.0
if(color_nor > umbral_valor):
poner_pixel = 255
else:
poner_pixel = 0
tupla_pixel = (poner_pixel, poner_pixel, poner_pixel)
imagen_nueva.putpixel((a, b), tupla_pixel)
return imagen_nueva
def mediana(arreglo):
if len(arreglo) % 2 == 1:
return arreglo[(len(arreglo)+1)/2-1]
else:
izq = arreglo[len(arreglo)/2-1]
der = arreglo[len(arreglo)/2]
return (float(izq + izq)) / 2.0
def obtener_original(path_imagen_original):
imagen = Image.open(path_imagen_original)
return imagen
def boton_bordes():
label.destroy()
#Pongo a grises
imagen_grises = cambiar_agrises(path_imagen_original)
imagen_grises.save("paso_1.jpg")
#Agrego diferencia
imagen_prom = diferencia(imagen_grises.convert("RGB"))
imagen_prom.save("paso_2.jpg")
#Agrego normalizacion
imagen_nor = normalizacion(imagen_prom)
imagen_nor.save("paso_3.jpg")
#Agrego umbral para binarizar
umbral_valor = 0.1
imagen_bin = cambiar_umbral(imagen_nor.convert("RGB"), umbral_valor)
imagen_bin.save("paso_4.jpg")
#Pongo promedio
imagen_prom = cambiar_promedio(imagen_bin.convert("RGB"))
imagen_prom.save("paso_5.jpg")
#Agrego umbral para binarizar
umbral_valor = 0.08
imagen_bin2 = cambiar_umbral(imagen_prom.convert("RGB"), umbral_valor)
imagen_bin2.save("paso_6.jpg")
#####
#Pongo promedio
imagen_prom = cambiar_promedio(imagen_bin2.convert("RGB"))
imagen_prom.save("paso_7.jpg")
#Pongo promedio
imagen_prom = cambiar_promedio(imagen_prom.convert("RGB"))
imagen_prom.save("paso_8.jpg")
#Agrego umbral para binarizar
umbral_valor = 0.5
imagen_BFS = cambiar_umbral(imagen_prom.convert("RGB"), umbral_valor)
imagen_BFS.save("paso_9.jpg")
aplicar_BFS(imagen_BFS)
def aplicar_BFS(imagen_BFS):
#aplica busqueda de anchura a todas las figuras encontradas con color aleatorio
pixeles = imagen_BFS.load()
x, y = imagen_BFS.size
colores = []
for a in range(x):
for b in range(y):
if pixeles[a, b] == (0, 0, 0):
color = (random.randint(0,255), random.randint(0,255), random.randint(0, 255))
imagen_BFS, masa = BFS(imagen_BFS.convert("RGB"), (a, b), color)
x_suma = 0
y_suma = 0
for i in range(len(masa)):
x_suma = x_suma + masa[i][0]
y_suma = y_suma + masa[i][1]
x_centro = x_suma/len(masa)
y_centro = y_suma/len(masa)
colores.append([color, 0, (x_centro, y_centro)])
pixeles = imagen_BFS.load()
masa = []
#suma la cantidad de colores diferentes en la imagen
pixeles = imagen_BFS.load()
for a in range(x):
for b in range(y):
for n in range(len(colores)):
if colores[n][0] == pixeles[a,b]:
colores[n][1] = colores[n][1] + 1
print colores
suma = 0
for i in range(len(colores)):
suma = suma + colores[i][1]
global frame
y = frame.winfo_height()
#Obtenemos porcentajes
prom = []
for i in range(len(colores)):
promedio = float(colores[i][1])/float(suma)*100.0
if promedio > 3.0:
print "Porcentajes: "
print "Figura " + str(i) + ": " + str(promedio)
prom.append((i, promedio, colores[i][0]))
maxim = 0.0
for i in range(len(prom)):
if maxim < prom[i][1]:
maxim = prom[i][1]
fig = prom[i][0]
color_max = prom[i][2]
#Itentificamos fondo y lo pintamos a gris
print "Fondo fig: " + str(fig)
imagen_BFS = pinta_fondo(imagen_BFS, color_max)
poner_imagen(imagen_BFS)
#Agregamos etiquetas segun su centro de masa
for i in range(len(colores)):
promedio = float(colores[i][1])/float(suma)*100.0
if promedio > 1.5:
print "Identifico . . ."
label_fig = Label(text = str(i))
label_fig.place(x = colores[i][2][0], y = colores[i][2][1] + y)
def pinta_fondo(imagen_BFS, color_max):
#pintamos fondo de manera que obtenemos el color que predomina en la imagen
pixeles = imagen_BFS.load()
x, y = imagen_BFS.size
for a in range(x):
for b in range(y):
if pixeles[a, b] == color_max:
color = (100,100,100)
imagen_BFS, masa = BFS(imagen_BFS.convert("RGB"), (a, b), color)
return imagen_BFS
def boton_original():
label.destroy()
global imagen_original
imagen_original = obtener_original(path_imagen_original)
poner_imagen(imagen_original)
path_imagen_original = "figuras2.jpg"
imagen_original = obtener_original(path_imagen_original)
ventana()
view raw identificar.py hosted with ❤ by GitHub

Esta sería mi tarea 2 de visión computacional, si tienen alguna duda, favor de hacérmelo saber.

1 comentario: