miércoles, 13 de febrero de 2013

Laboratorio 2

Laboratorio 2 - Ruido sal y pimienta, normalización y binarización

Hola, en esta entrada voy a presentar el trabajo realizado para el laboratorio 2 de Visión computacional.

Lo primero (obligatorio) que hice fue generar ruido de sal y pimienta en imágenes a colores, la manera en la que puse los puntos blancos y negros sobre la imagen fue muy sencilla. Cuando ejecuto el python, paso como parámetro 2 valores, el primero es la intensidad (ruido a generar en la imagen), y luego la polarización (que tan blancos o negros van a ser las sales y pimientas). El valor de la intensidad lo pongo dentro de un random para que la probabilidad en que salgan puntos (ya sea blancos o negros) dependan del valor dado.

Luego el valor de la polarización lo determino mediante condicionales, para ver que tan negros o blancos pongo los ruidos, tomando en cuenta que el valor 0 corresponde a negro y el valor 255 corresponde a blanco, con el valor leido de polarización solo vario entre esos 2 números.

Bueno, aquí muestro la subrutina con la que realicé el ruido:

def salPimienta(): # Subrutina para poner sal y pimienta a la imagen binarizada
 #tiempoInicial = time.time()
 i = 0
 x = 0
 y = 0

 #Valores para instensidad y polarizacion respectivamente
 intensidad = int(argv[1]) # Nivel de pixeles (cantidades)
 polarizacion = int(argv[2]) # Que tan negros y blancos son los puntos en porcentaje... donde 0 es negro y 255 es blanco

 im = Image.open("bla.jpg")
  pix = im.load()
 for x in xrange(im.size[0]):
  for y in xrange(im.size[1]):
   #pix = im.load()
   tupla = pix[x, y]
   azar = int(random.randint(0,intensidad))

   if azar == 9: #Aqui podria ser perfectamente cualquier numero (no necesariamente 9), seria la misma probabilidad: 1/intensidad
    if polarizacion > 25 and polarizacion < 75: 
     a = 128 + 64
     b = 128 + 64  # Para puntos "blancos"
     c = 128 + 64

     # Fabricando la nueva tupla
     tupla1 = (a, b, c)
     
     # Poniendo pixel
     im.putpixel((x, y), tupla1)
    
    elif polarizacion >= 75:
     a = 255
     b = 255 # Para puntos "blancos"
     c = 255
     
     # Fabricando la nueva tupla
     tupla1 = (a, b, c)

     #Poniendo pixel
     im.putpixel((x, y), tupla1)

    elif polarizacion <= 25:
     a = 128 + 20
     b = 128 + 20 # Para puntos "blancos"
     c = 128 + 20
     
     # Fabricando la nueva tupla 
     tupla1 = (a, b, c)

     #Poniendo pixel
     im.putpixel((x, y), tupla1)
  
   elif azar == 7:
    if polarizacion > 25 and polarizacion < 75: 
     d = 128 - 64
     e = 128 - 64 # Para puntos "negros"
     f = 128 - 64
     tupla2 = (d, e, f)
     im.putpixel((x, y), tupla2)

    elif polarizacion >= 75:
     d = 0
     e = 0 # Para puntos "negros"
     f = 0
     tupla2 = (d, e, f)
     im.putpixel((x, y), tupla2)
    
    elif polarizacion <= 25:
     d = 128 - 20
     e = 128 - 20 # Para puntos "negros"
     f = 128 - 20
     tupla2 = (d, e, f)
     im.putpixel((x, y), tupla2)
     

   else:
    a = tupla[0]
    b = tupla[1]
    c = tupla[2] 
    
    newTupla = (a,b,c)
    im.putpixel((x, y), newTupla)   

   #print tupla, "--", a,",",b,",",c
 im.save('meh6.jpg')
 #tiempoFinal = time.time()
 #transcurso = tiempoFinal - tiempoInicial
 #print "Tiempo de escala de grises = ", transcurso 


Ahora les muestro imágenes con distintos niveles de intensidad y polarización:



(Intensidad 60%, polarización 50%)



(Intensidad 90%, polarización 100%)



Ahora para quitar ese ruido generado hice otra subrutina, que lo que hace es compara pixel por pixel de la imagen, cuando detecta que el pixel es blanco o negro, genera un promedio con los valores de pixeles de los vecinos, seguido de eso el promedio obtenido se lo asigna al pixel en el que está posicionado.

A continuación les muestro la subrutina que realiza este proceso:

def quitarSalPimienta():
 
 i = 0
 x = 0
 y = 0
 im = Image.open("meh6.jpg")
 pix = im.load() 
 width, height = im.size
 promedio = 0
 width = width-1
 height = height-1

 #x = j y y = i
 for x in range(height):
  for y in range(width):
   
   tupla = pix[y, x]
   pR = tupla[0]
   pG = tupla[1]
   pB = tupla[2]
  
   print tupla   
   
   #if (pB == 0 or pR == 255): 
   if (pR >= 240 or pG >= 240 or pB >= 240) or (pR <=10 or pG <=10 or pB <=10):
    #esquina superior izquierda
    if y == 0 and x == 0:
     #promedio = (sum(pix[y + 1,x])/3 + sum(pix[y,x + 1])/3 + sum(pix[y,x])/3)/3
     promedio1 = (pix[y + 1,x][0] + pix[y,x + 1][0])/2
     promedio2 = (pix[y + 1,x][1] + pix[y,x + 1][1])/2
     promedio3 = (pix[y + 1,x][2] + pix[y,x + 1][2])/2
    #esquina superior derecha 
    if y == width and x == 0:
     #promedio = (sum(pix[y,x+1])/3 + sum(pix[y-1,x])/3 + sum(pix[y,x])/3)/3
     promedio1 = (pix[y,x+1][0] + pix[y-1,x][0])/2
     promedio2 = (pix[y,x+1][1] + pix[y-1,x][1])/2 
     promedio3 = (pix[y,x+1][2] + pix[y-1,x][2])/2

    if y == 0 and x == height:
      #promedio = (sum(pix[y,x-1])/3 + sum(pix[y+1,x])/3 + sum(pix[y,x])/3)/3
     promedio1 = (pix[y,x-1][0] + pix[y+1,x][0])/2
     promedio2 = (pix[y,x-1][1] + pix[y+1,x][1])/2
     promedio3 = (pix[y,x-1][2] + pix[y+1,x][2])/2

    if y == height and x == width:
      #promedio = (sum(pix[y - 1,x])/3 + sum(pix[y,x - 1])/3 + sum(pix[y,x])/3)/3
     promedio1 = (pix[y - 1,x][0] + pix[y,x - 1][0])/2
     promedio2 = (pix[y - 1,x][1] + pix[y,x - 1][1])/2
     promedio3 = (pix[y - 1,x][2] + pix[y,x - 1][2])/2


    if y > 0 and y < width and x == 0:
     #promedio = (sum(pix[y+1,x])/3 + sum(pix[y-1,x])/3 +sum(pix[y,x+1])/3+ sum(pix[y,x])/3)/4
     promedio1 = (pix[y+1,x][0] + pix[y-1,x][0] + pix[y,x+1][0])/3
     promedio2 = (pix[y+1,x][1] + pix[y-1,x][1] + pix[y,x+1][1])/3
     promedio3 = (pix[y+1,x][2] + pix[y-1,x][2] + pix[y,x+1][2])/3
  
    if y > 0 and y < width and x == height:
     #promedio = (sum(pix[y -1,x])/3 + sum(pix[y,x-1])/3 +sum(pix[y+1,x])/3+ sum(pix[y,x])/3)/4
     promedio1 = (pix[y -1,x][0] + pix[y,x-1][0] + pix[y+1,x][0])/3
     promedio2 = (pix[y -1,x][1] + pix[y,x-1][1] + pix[y+1,x][1])/3
     promedio3 = (pix[y -1,x][2] + pix[y,x-1][2] + pix[y+1,x][2])/3

    if x >0 and x 0 and x < height:
     #promedio = (sum(pix[y - 1,x])/3 + sum(pix[y,x-1])/3 + sum(pix[y,x +1])/3+ sum(pix[y,x])/3)/4
     promedio1 = (pix[y - 1,x][0] + pix[y,x-1][0] + pix[y,x +1][0])/3
     promedio2 = (pix[y - 1,x][1] + pix[y,x-1][1] + pix[y,x +1][1])/3
     promedio3 = (pix[y - 1,x][2] + pix[y,x-1][2] + pix[y,x +1][2])/3

    if y > 0 and y< width and x>0 and x< height:
     #promedio = (sum(pix[y,x])/3 + sum(pix[y + 1,x])/3 + sum(pix[y - 1,x])/3 + sum(pix[y,x + 1])/3 + sum(pix[y,x -1])/3)/5 
     promedio1 = (pix[y + 1,x][0] + pix[y - 1,x][0] + pix[y,x + 1][0] + pix[y,x -1][0])/4
     promedio2 = (pix[y + 1,x][1] + pix[y - 1,x][1] + pix[y,x + 1][1] + pix[y,x -1][1])/4
     promedio3 = (pix[y + 1,x][2] + pix[y - 1,x][2] + pix[y,x + 1][2] + pix[y,x -1][2])/4
   #-----------------------------
   #tupla = pix[x, y]
   
    a = promedio1
    b = promedio2
    c = promedio3 
    miTupla = (a,b,c) #Eso no es una tupla, pero asi le digo yo :P
    im.putpixel((y, x), miTupla) #Esto si es una tupla
    #pix[y, x] = (a,b,c)
   
   else: 
    tuplaOriginal = (pR, pG, pB) #Esto tampoco es una tupla, pero asi le digo yo :P
    im.putpixel((y, x), tuplaOriginal) #Esto si es una tupla XD
   '''
   newTupla = (prom,prom,prom)
   im.putpixel((x, y), newTupla) 
   '''  

   #print tupla, "--", a,",",b,",",c
 im.save('meh7.jpg')


Ahora les muestro imágenes con ruido generado comparadas con las imágenes después de pasar por el fitro que limpia el ruido:


  
   
Normalización y binarización

Bien, para los puntos extra, hice una imagen difusa, luego realicé la diferencia entre la imagen original y la difusa y al final realicé la normalizacion y binarización.

Los métodos para realizar estos filtros los describí en el post anterior (Tarea 1), pero aquí explico superficialmente que la difusa la realicé con los promedios de los vecinos que se van visitando en cada pixel, la diferencia es tan solo una resta entre los valores de los pixeles que componen la imagen original y la imagen difusa. La normalización y binarización se realizan tan solo poniendo umbrales y comparando que tan oscuros o claros son los valores de los pixeles, para luego ponerlos en una categoría de blanco o negro (0 o 255).

A continuación les muestro la subrutina del proceso de difusa:


def filtrada(): #Filtrada por el metodo de los vecinos
 #tiempoInicial = time.time()
 i = 0
 x = 0
 y = 0
 im = Image.open("meh.jpg")
 width, height = im.size
 pix = im.load() 
 promedio = 0
 width = width-1
 height = height-1

 #x = j y y = i
 for x in range(height):
  for y in range(width):
   #esquina superior izquierda
   if y == 0 and x == 0:
    promedio = (sum(pix[y + 1,x])/3 + sum(pix[y,x + 1])/3 + sum(pix[y,x])/3)/3
   #esquina superior derecha
   if y == width and x == 0:
    promedio = (sum(pix[y,x+1])/3 + sum(pix[y-1,x])/3 + sum(pix[y,x])/3)/3

   if y == 0 and x == height:
     promedio = (sum(pix[y,x-1])/3 + sum(pix[y+1,x])/3 + sum(pix[y,x])/3)/3

   if y == height and x == width:
     promedio = (sum(pix[y - 1,x])/3 + sum(pix[y,x - 1])/3 + sum(pix[y,x])/3)/3

   if y > 0 and y < width and x == 0:
    promedio = (sum(pix[y+1,x])/3 + sum(pix[y-1,x])/3 +sum(pix[y,x+1])/3+ sum(pix[y,x])/3)/4
  
   if y > 0 and y < width and x == height:
    promedio = (sum(pix[y -1,x])/3 + sum(pix[y,x-1])/3 +sum(pix[y+1,x])/3+ sum(pix[y,x])/3)/4

   if x >0 and x 0 and x < height:
    promedio = (sum(pix[y - 1,x])/3 + sum(pix[y,x-1])/3 + sum(pix[y,x +1])/3+ sum(pix[y,x])/3)/4

   if y > 0 and y< width and x>0 and x< height:
    promedio = (sum(pix[y,x])/3 + sum(pix[y + 1,x])/3 + sum(pix[y - 1,x])/3 + sum(pix[y,x + 1])/3 + sum(pix[y,x -1])/3)/5 
 


   #-----------------------------
   #tupla = pix[x, y]
   
   a = promedio
   b = promedio
   c = promedio 
   '''
   a = tupla[0]
   b = tupla[1]
   c = tupla[2]
   '''
   #prom = int((a+b+c)/3)
   pix[y, x] = (a,b,c)
   #tup = pix[]
   #im.putpixel((y, y), pix)   

   #print tupla, "--", a,",",b,",",c
 im.save('meh2.jpg')
 #tiempoFinal = time.time()
 #transcurso = tiempoFinal - tiempoInicial
 #print "Tiempo transcurrido durante la filtracion = ", transcurso


Luego la diferencia y la binarización:

def diferencia(): #O normalizacion
 #tiempoInicial = time.time()
 imagen1 = Image.open("meh.jpg")
 imagen2 = Image.open("meh2.jpg")
 width, height = imagen1.size
 pix = imagen1.load()
 pix2 = imagen2.load()

 for y in range(width):
  for x in range(height):
   (a,b,c) = pix[y, x]
   (d,e,f) = pix2[y, x]
   promedio = a+b+c/3
   promedio1 = d+e+f/3
   promedio2 = promedio - promedio1

   if promedio2 > 115:
    promedio2 = 255
   else:
    promedio2 = 0
   a = promedio2
   b = promedio2
   c = promedio2  
   pix[y, x] = (a,b,c)
 imagen1.save("meh3.jpg")
 #tiempoFinal = time.time()
 #transcurso = tiempoFinal - tiempoInicial
 #print "Tiempo transcurrido durante la normalizacion = ", transcurrido


Subrutina para binarización:

def umbrales():
 #tiempoInicial = time.time()
 i = 0
 x = 0  
 y = 0
 umbInferior = 77
 umbSuperior = 177
 im = Image.open("meh4.jpg")
 
 for x in xrange(im.size[0]):
  for y in xrange(im.size[1]):
   pix = im.load()
   tupla = pix[x, y]
 
   a = tupla[0]
   b = tupla[1]
   c = tupla[2]
   
   prom = int((a+b+c)/3)
   if prom < umbInferior:
    prom = 0
   elif prom >= umbSuperior:
    prom = 255
   newTupla = (prom,prom,prom)
   im.putpixel((x, y), newTupla)   

   #print tupla, "--", a,",",b,",",c
 im.save('meh5.jpg')
 #tiempoFinal = time.time()
 #transcurrido = tiempoFinal - tiempoInicial
 #print "Tiempo transcurrido durante la binarizacion = ", transcurrido


Ya por último les muestro las imágenes después de pasar por todos los procesos antes mencionados:
(Original)



(Escala de grises)



(Difusa)

(Diferencia)



(Binarización)



Git sobre todo el trabajo realizado hasta ahora: https://github.com/eddypre/VisionTriana
 
 
Cualquier duda o aclaración pueden dejarla en comentarios.

Saludos a todos!

 

1 comentario: