Mostrando entradas con la etiqueta Visión Computacional. Mostrar todas las entradas
Mostrando entradas con la etiqueta Visión Computacional. Mostrar todas las entradas

martes, 23 de abril de 2013

Tarea 6: Detección de Agujeros

Para ésta semana en la clase de visión se nos pidió hacer la detección de agujeros a partir de una imagen dada, tanto así obtener su centro, rellenar el agujero y obtener el porcentaje que tiene.

Importancia:
La detección de agujeros es una de las repuestas que se aplican principalmente en la industria de la manufactura, enfocada principalmente en en la creación de piezas sólidas. Un ejemplo a mencionar es al momento de detectar fisuras u orificios en las piezas que se elaboraron, en la cual ayudan a clasificarlas, ya sea para quitarlas de la línea de producción u obtener las que no tienen imperfecciones.

Desarrollo:
Dejo el código incompleto en la cuál obtuve los histogramas, faltando implementar, la parte del bfs y detección de centros.
Resultados y Notas:
Para poder tener una buena detección de histogramas, recomiendo hacer el uso de filtros o normalizar la imagen, en mi caso lo que emplie fue ordenar la lista, ya que sin el uso de éste, lo que se obtendría sería muchas líneas horizontales y verticales.

[imagen original]

[primeros resultados]

[imagen sin filtros]

[imagen sin filtro]


Referencia:
http://elisa.dyndns-web.com/~elisa/teaching/comp/vision/agujeros.pdf

lunes, 15 de abril de 2013

Detección de Elipses

Para ésta ocasión se nos pidió hacer la detección de elipses dada una imagen, a continuación dejo el código que lo tengo incompleto, pero en si lo que busco es obtener el número de intersecciones que se tiene de la figura, obtenida de los puntos de borde y su gradiente, para así conocer su centro del elipse.

Código:
Para el código me base en los anteriores que tenía donde se aplica escala de grises, convolusión, defección de formas y normalizar, deja aquí la liga.



Referencias:
http://www.wikillerato.org/Circunferencias_tangentes_conocido_el_punto_de_tangencia.html

jueves, 7 de marzo de 2013

Actividad 5: Detección Círculos Radios Desconocidos

Para ésta entrada se nos encargó hacer la detección de círculos donde nosotros no conocemos el radio y buscamos que nuestro programa lo detecte.

A continuación les dejo el código el cuál esta incompleto, pero proximamente lo actualizaré.
Resultados




martes, 5 de marzo de 2013

Tarea 4: Detección de Círculos

Para esta entrada, se nos encargó que detectáramos los círculos de una imagen, lo primero que se hizo fue descubrir cuales son los centros del círculo, para después resaltar el borde del círculo, para poder obtener el círculo necesitamos un radio, así que éste nosotros lo fuimos proporcionando.

Para el proceso de la imagen se empleo nuevamente la transformada de Hough, la diferencia es que le agregaremos unas fórmulas para obtener el centro del círculo.

Fórmula del gradiente:

[https://files.nyu.edu/jb4457/public/files/research/bristol/hough-report.pdf]

Theta:
[https://files.nyu.edu/jb4457/public/files/research/bristol/hough-report.pdf]

Obtener centro de x & y:

donde x & y son los puntos de circunsferencia del círculo y a & b el centro del círculo, como nosotros buscamos encontrar a & b, despejamos en la ecuación teniendo la siguiente fórmula:

Código:
A continuación les dejo el código.
Resultado:
[radio = 60]

Notas:
El código ésta incompleto, por problemas nocturnos (dormido) y solo podemos distinguir los puntos que se obtienen, pronto lo actualizaré.

Referencias:
https://files.nyu.edu/jb4457/public/files/research/bristol/hough-report.pdf

lunes, 25 de febrero de 2013

Tarea 3: Detección de Líneas

Para esta semana se nos encargó detectar las líneas verticales y horizontales que tiene o pudiera tener una imagen.

Para poder realizar detectar las líneas antes que nada la imagen la tuvimos que haber pasado en escala de grises, binarizada, para después aplicar la convolución y  finalmente la transformada de hough.

Una vez llegado a convolución (en mi caso apliqué las máscaras de prewitt en x & y) nosotros tendremos dos arreglos uno que son los bordes de la imagen en x y otro en y, una vez obtenido esto (gradientes horizontales y verticales) calcularemos para después obtener el ángulo de los pixeles.

Donde las fórmulas aplicadas para obtener del ángulo son theta y rho:


[http://elisa.dyndns-web.com/~elisa/teaching/comp/vision/lineas.pdf]

Donde p es rho y este nos servirá para hacer un matriz y poner las líneas que se detectan en el ángulo.

Código:

A continuación les dejo el código, pueden checar en las entrada anteriores para hacer la escala de grises, pasarla a binario y tener la convolusion.


Resultados:




Notas:
Se podría experimentar con el código un poco aplicando diferentes máscaras y viendo que diferentes resultados nos pudiera dar, al igual de tratar de obtener las líneas sin pasar necesariamente de la binarización, escala de grises y los límites de gx & gy que nos pudiera dar cuáles son las líneas continuas.

Referencias:
http://es.wikipedia.org/wiki/Transformada_de_Hough
http://elisa.dyndns-web.com/~elisa/teaching/comp/vision/lineas.pdf
http://www.slideshare.net/omarspp/segmentacin-de-imagen
http://dmi.uib.es/~aortiz/4730-tema8.pdf
http://alojamientos.us.es/gtocoma/pid/tema4.pdf

miércoles, 13 de febrero de 2013

PIL: Putpixel and Getpixel vs Array

En ésta entrada, veremos una comparativa respecto a la demora que se lleva en el procesamiento de una imagen con la librería de PIL.
Realizando las tareas respecto al tema, me encontré con un ligero problema que al analizarlo y compararlo tiene consecuencias como esperar un resultado de una determinada imagen. Así que me puse a investigar y buscar otra forma del poder procesar una imagen con PIL y me encontré con el uso de arreglos manipulados con la misma imagen.

Breve discusión:
Siendo un poco breve y analizando mi código encontré que las subrutinas getpixel y putpixel son un poco pesadas, ya que estamos manipulando y procesando la imagen en el momento que se carga determinado pixel y su determinado color, a comparación del uso de las listas con la subrutina load() donde cargamos la imagen en el arreglo, donde cada elemento contiene una tupla, siendo más ligera y fácil su manipulación.

Código:
En el siguiente código veremos como trabaja el procesar una imagen con lo ya antes mencionado aplicada a una imagen normal buscando obtener la escala de grises.

img.putpixel() & img.getpixel
img.load()


Resultados:
[511x684]

[511x684]

Como podemos notar en la siguiente imagen haciendo varios test de la misma imagen se encontró que el primer tiempo arrojado emplea el uso de getpixel y putpixel teniendo una demora aproximada de 3.2 segundos y en el segundo empleado el uso de arreglos obtuvo una demora aproximada de 0.7 segundos.
Podemos discutir que se tiene una reducción del 82% del tiempo empleado, siendo una mejora muy significante en el tiempo al momento de manipular imagenes.


Código Completo:

martes, 12 de febrero de 2013

Actividad 2: Ruido Sal y Pimienta

En esta entrada veremos como meter y quitar ruido. El ruido que se empleará es sal y pimienta en la cuál consiste que en una imagen dada tiene algunos pixeles en blanco y negro.

Importancia
Es importante saber como quitar en una imagen ruido, ya que nos podemos encontrar que en un imagen   su contenido sea afectado por la lente de la cámaras, ondas magnéticas, entre otras.

Sal y Pimienta
Para generar el ruido lo que se pide es la intensidad, donde nos servirá para que tan frecuente tendremos ruido en la image, entonces lo que hacemos es tomar un de forma aleatoria aleatoria, para después darle a ese mismo pixel una tonalidad blanca o negra.


[intensidad 0.01]

[intensidad 0.05]

[intensidad 0.1]

Remover Sal y Pimienta
Para remover el pixel de sal y pimienta, se pueden emplear varias técnicas, en mi caso empleo la técnica de media aritmética, donde consiste en tomar el pixel actual y sus vecinos, dentro de cada pixel estará su rgb, así que lo ordenamos y sacamos su valor medio, para después meterlo a la lista donde pondremos el actual con sus vecinos, para hacer nuevamente el mismo proceso, que es ordenarlo y sacar el valor medio, una vez obtenido ese valor es el que se pondrá en el pixel actual.

Resultado:
A continuación dejo el resultado y como podemos ver en la imagen que se removió sal y pimienta es casi efectivo, ya que podemos ver a simple vista uno o dos pixeles con ruido.

[Sal y Pimienta]

[Remover Sal y Pimienta]

Código Completo:


Referencias:

lunes, 11 de febrero de 2013

Tarea 1: Detección de Bordes

En ésta entrada veremos como detectar bordes en una determinada imagen, aplicando una máscara de convolución a nuestra matriz de la imagen. En esta entrada veremos aplicado con dos operadores (Sobel y Prewitt), que nos ayudarán a sacar la aproximación del gradiente, calculando la intensidad de la imagen en cada pixel.

Si no sabemos que es el gradiente, podemos explicarlo decir que es un vector, donde nos muestra la dirección en la que un determinado punto crece más rápido.

Aplicado
Para poder detectar los bordes de una imagen ocupamos la combinación de tres cosas: imagen a escala de grises + cualquier filtro en la imagen + máscara(puede ser Sobel, Prewitt ó alguna otra). En mi caso el tipo de Filtro que apliqué en la imagen es la de Blur y utilicé ambas máscaras.

Sobel
Esta máscara es de un tamaño de 3x3, donde tendremos dos matrices una aplicada en Gx y otra en Gy (primera imagen), para después combinarlos y tener la magnitud del gradiente (segunda imagen).


[http://es.wikipedia.org/wiki/Operador_Sobel]

Prewitt
Al igual que Sobel es una máscara de 3x3, donde se tienen dos matrices una aplicada en Gx y otra en Gy (primera imagen), para después combinarlas y tener su gradiente (segunda imagen).


[http://en.wikipedia.org/wiki/Prewitt_operator]

Código
A continuación les dejo el código con una breve explicación donde menciona las fórmulas empleadas mencionadas anteriormente, al igual dejo la liga de mi git.



Resultados
Con los resultados obtenidos, podemos decir que aplicando la mascara de Sobel o Prewitt, no se tiene mucha diferencia en la imagen, más que la imagen un poco más opaca que la otra.

[imagen original]

[imagen escala de grises]

[imagen filtro blur 5 iteraciones]

[imagen Sobel]

[imagen Prewitt]

Jugando un Poco
Jugando un poco con las imagenes y que otros resultados podemos tener, ya sea aplicando el gradiente en x, y o al igual si se toma la imagen sin el filtro. Podemos decir que en x podemos observar los bordes que se tienen en horizontal y en y los que tenemos en vertical.

[gradiente en X]

[gradiente en Y]

[sin filtro Sobel]

[sin filtro Prewitt]

Referencias
http://es.wikipedia.org/wiki/Operador_Sobel
http://en.wikipedia.org/wiki/Prewitt_operator
http://www.songho.ca/dsp/convolution/convolution2d_example.html
http://docs.gimp.org/es/plug-in-convmatrix.html

lunes, 4 de febrero de 2013

Actividad 1: Filtros


En ésta entrada veremos como aplicar diferentes tipos de filtros a una determinada imagen, para eso se empleo python junto con la librería PIL, donde los filtros aplicados son:
  • Escala de grises.
  • Escala de grises mínimo.
  • Escala de grises máximo.
  • Negativo.
  • Binaria.
El programa lo que hace es mostrarte en una ventana la imagen seleccionada, donde en la misma ventana te muestran botones para aplicar las diferentes tipos de escalas, al final dejo el código completo junto a la liga de github.


Algoritmo:
Para poder sacar los filtros primero se obtuvo cada pixel de la imagen, para después tener el rgb.

Escala de grises:
En la escala de grises, una vez obtenido el rgb del pixel, sacamos su media y este nuevo valor será el del rojo, verde y azul, para así obtener el nuevo pixel.
    def grayScale(self):
        for i in range(self.img.size[0]): #recorremos las de i & j para tener cada pixel de la iamgen
            for j in range(self.img.size[1]):
                r = self.rgb.getpixel((i, j))[0] #obtenemos r, g, b
                g = self.rgb.getpixel((i, j))[1]
                b = self.rgb.getpixel((i, j))[2]
                
                media = (r+g+b)/3 #Lo explicado
                pixel = tuple([media, media, media]) #Creamos nuestro nuevo pixel
                self.img.putpixel((i, j), pixel) #En la imagen ponemos el nuevo pixel           

        self.img.save('grayScale.png', 'PNG') #Guardamos la imagen
        return self.img #regresamos la imagen, para manipolarla posteriormente


[escala de grises]


Escala de grises máximo y mínimo
En ésta escala de grises, lo que hago es obtener el pixel completo, sacando el máximo o mínimo del rgb, para después el obtenido ponerlo en cada rbg
    def grayScaleMax(self):
        for i in range(self.img.size[0]): #Se aplica lo mismo mencionado
            for j in range(self.img.size[1]):
                
                pixel = max(self.rgb.getpixel((i, j))) #Sacamos el máximo
                
                pixel = tuple([pixel, pixel, pixel])
                self.img.putpixel((i, j), pixel)            

        self.img.save('grayScaleMax.png', 'PNG')
        return self.img

    def grayScaleMin(self):
        for i in range(self.img.size[0]):
            for j in range(self.img.size[1]):
                
                pixel = min(self.rgb.getpixel((i, j))) #Sacamos en mínimo
                
                pixel = tuple([pixel, pixel, pixel])
                self.img.putpixel((i, j), pixel)            

        self.img.save('grayScaleMin.png', 'PNG')
        return self.img


[escala de grises mínimo]

[escala de grises máximo]


Umbral:
El del umbral, interactúa un poco con el de la escala de grises, ya que nosotros pondremos un límite del valor obtenido (media), en mi caso si es mayor a 127 es 255, de lo contrario es 0.
    def binaryScale(self, umbral):
        if(umbral == None): umbral = 122
        for i in range(self.img.size[0]):
            for j in range(self.img.size[1]):
                r = self.rgb.getpixel((i, j))[0]
                g = self.rgb.getpixel((i, j))[1]
                b = self.rgb.getpixel((i, j))[2]
                
                media = (r+g+b)/3 #Obtenemos la media
                pixel = tuple([media, media, media])
                self.img.putpixel((i, j), pixel)            

                if media > umbral: media = 255 #Dependiendo del umbral nos asigna el nuevo valor
                else: media = 0

                pixel = tuple([media, media, media])
                self.img.putpixel((i, j), pixel)

        self.img.save('BinaryScale.png', 'PNG')
        return self.img


[filtro binario]


Negativo:
Investigando un poco del algoritmo para sacar el negativo, lo que se hace es tener el valor maximo de un color (el cual es 255) y éste es restado por el valor de cada rgb, pra despues tener el pixel.
    def negativeScale(self):
        for i in range(self.img.size[0]):
            for j in range(self.img.size[1]):
                r = self.rgb.getpixel((i, j))[0]
                g = self.rgb.getpixel((i, j))[1]
                b = self.rgb.getpixel((i, j))[2]
                
                nr = 255 - r # 255 que es nuestro valor máximo es restado por rgb
                ng = 255 - g
                nb = 255 - b
                pixel = tuple([nr, ng, nb])
                self.img.putpixel((i,j), pixel)

        self.img.save('negativeScale.png', 'PNG')
        return self.img


[filtro negativo]



Código:
Al igual dejo el enlace de github.

from Tkinter import * 
from PIL import ImageTk, Image
from sys import argv

class Filtro(object):
    """docstring for Filtro"""
    def __init__(self, fileName):
        self.img = Image.open(fileName)
        self.rgb = self.img.convert('RGB')

    def grayScale(self):
        for i in range(self.img.size[0]):
            for j in range(self.img.size[1]):
                r = self.rgb.getpixel((i, j))[0]
                g = self.rgb.getpixel((i, j))[1]
                b = self.rgb.getpixel((i, j))[2]
                
                media = (r+g+b)/3
                pixel = tuple([media, media, media])
                self.img.putpixel((i, j), pixel)            

        self.img.save('grayScale.png', 'PNG')
        return self.img

    def grayScaleMax(self):
        for i in range(self.img.size[0]):
            for j in range(self.img.size[1]):
                
                pixel = max(self.rgb.getpixel((i, j)))
                
                pixel = tuple([pixel, pixel, pixel])
                self.img.putpixel((i, j), pixel)            

        self.img.save('grayScaleMax.png', 'PNG')
        return self.img

    def grayScaleMin(self):
        for i in range(self.img.size[0]):
            for j in range(self.img.size[1]):
                
                pixel = min(self.rgb.getpixel((i, j)))
                
                pixel = tuple([pixel, pixel, pixel])
                self.img.putpixel((i, j), pixel)            

        self.img.save('grayScaleMin.png', 'PNG')
        return self.img

    def binaryScale(self, umbral):
        if(umbral == None): umbral = 122
        for i in range(self.img.size[0]):
            for j in range(self.img.size[1]):
                r = self.rgb.getpixel((i, j))[0]
                g = self.rgb.getpixel((i, j))[1]
                b = self.rgb.getpixel((i, j))[2]
                
                media = (r+g+b)/3
                pixel = tuple([media, media, media])
                self.img.putpixel((i, j), pixel)            

                if media > umbral: media = 255
                else: media = 0

                pixel = tuple([media, media, media])
                self.img.putpixel((i, j), pixel)

        self.img.save('BinaryScale.png', 'PNG')
        return self.img

    def negativeScale(self):
        for i in range(self.img.size[0]):
            for j in range(self.img.size[1]):
                r = self.rgb.getpixel((i, j))[0]
                g = self.rgb.getpixel((i, j))[1]
                b = self.rgb.getpixel((i, j))[2]
                
                nr = 255 - r
                ng = 255 - g
                nb = 255 - b
                pixel = tuple([nr, ng, nb])
                self.img.putpixel((i,j), pixel)

        self.img.save('negativeScale.png', 'PNG')
        return self.img


path_image = sys.argv[1]
debug = True
imagen = Filtro(path_image)#Instanciamos la imagen de la clase filtro

def main():
    window()

def window():
 root = Tk()
 frame = Frame()
 frame.pack(fill=X, padx=5, pady=5)
 root.title("Imagen Original")

 call(Image.open(path_image)) #Ponemos la imagen original

 panel1 = Button(text="Original", command=original)
 panel1.pack(in_=frame, side=LEFT)

 panel2 = Button(text="GrayScale", command=grayScale)
 panel2.pack(in_=frame, side=LEFT)

 panel3 = Button(text="GrayScaleMin", command=grayScaleMin)
 panel3.pack(in_=frame, side=LEFT)

 panel4 = Button(text="GrayScaleMax", command=grayScaleMax)
 panel4.pack(in_=frame, side=LEFT)
 
 panel5 = Button(text="BinaryScale", command=binaryScale)
 panel5.pack(in_=frame, side=LEFT)

 panel6 = Button(text="Negative", command=negativeScale)
 panel6.pack(in_=frame, side=LEFT)
 
 root.mainloop()

def call(im): #Metodo que ponemos la nueva imagen
    global panel
    img = ImageTk.PhotoImage(im)
    panel = Label(image = img)
    panel.pict = img
    panel.pack() 

def original(): #Metodo del Boton para llamar la imagen Original
 panel.destroy()   #Destruimos el panel para poner la nueva imagen
 return call(Image.open(path_image)) 

def grayScale(): #Metodo del Boton para llamar la escala de grises
 global imagen
 panel.destroy()
 call(imagen.grayScale()) # de nuestro objeto imagen mandamos llamar la funcion

def grayScaleMin(): #Metodo del Boton para llamar la escala de grises de min
 global imagen
 panel.destroy()
 call(imagen.grayScaleMin())

def grayScaleMax(): #Metodo del Boton para llamar la escala de grises de max
 global imagen
 panel.destroy()
 call(imagen.grayScaleMax())

def binaryScale(): #Metodo del Boton para llamar la escala binaria
 global imagen
 panel.destroy()
 call(imagen.binaryScale(None))

def negativeScale(): #Metodo del Boton para llamar la imagen en negativo
 global imagen
 panel.destroy()
 call(imagen.negativeScale())

if __name__ == '__main__':
    main()

Nota:
Debo de mencionar que me apoyé del crear y poner la imagen en la ventana del código de un compañero de clase, todo lo demás lo algorítmico del procesamiento de imagenes es de mi parte.


Referencias:
http://lodev.org/cgtutor/filtering.html
http://www.pythonware.com/library/tkinter/introduction/hello-again.htm

martes, 22 de enero de 2013

Detección de carros vía aérea

Para esta entrada se pidió buscar un artículo que fuera relacionada con las aplicaciones de visión computacional.



Lo que busca este artículo es detectar carros vía fotos aéreas, el problema que esta resolviendo es detectar los objetos que en este caso son carros pequeños, las sombras que hay en ellas y las variaciones que se tiene en la imagen en diferentes puntos de vista.