martes, 21 de abril de 2015

Introducción y manipulación básica de imagenes

Introduccion

El propósito de este blog es  llenar un vacío en habla Hispana sobre fotografía computacional, La bibliografía en Ingles es abundante pero en castellano no he logrado encontrar ningún grupo que se dedique a este tema. Cada día la fotografía y el cine van ocupando mas lugar tanto como entretenimiento como docencia y  redes sociales. Entre todas las posibilidades de abordar este tema se ha elegido trabajar con software libre en plataforma Linux, como lenguaje de programación el Python, usando las librerías Numpy y OpenCV.


Requisitos


Conocimientos básicos de Algebra Lineal, Calculo.
Programación básica en python
Los requisitos es tener una computadora con una version de Linux con Python 2.6  y las librerias Numpy y OpenCV.
Una cámara fotográfica para capturar las imágenes a trabajar.

Numpy


NumPy es el paquete fundamental para la computación científica con Python . Contiene entre otras cosas : 
  • Un poderoso objeto  matriz N - dimensional 
  • Funciones  avanzadas 
  • Herramientas para la integración de C / C ++ y Fortran 
  • Álgebra lineal, transformada de Fourier , capacidades de números aleatorios.


Además de sus usos científicos obvias, NumPy también puede ser utilizado como un contenedor multi- dimensional eficiente para la manipulación de datos genéricos. Se pueden definir tipos arbitrarios de datos. Esto permite a NumPy  integrar sin problemas y rápidamente con una amplia variedad de bases de datos. Numpy está licenciado bajo la licencia BSD , lo que permite su re-utilización con pocas restricciones.
Instalacion de Numpy pude verse aqui.

OpenCV

OpenCV (Open Source Computer vsion Library : http://opencv.org ) es una biblioteca de licencia  de código abierto BSD que incluye varios cientos de algoritmos de visión por computador. El documento describe el llamado OpenCV API 2.x, que es esencialmente una API en  C ++, como opuesta a la API 1.x OpenCV  basado en C . Este último se describe en opencv1x.pdf .

Para instalar opencv seguir los pasos descriptos en la siguiente pagina.

Fotografia Computacional.

Primero vamos a definir que es fotografía, la definición mas elemental es "Dibujar con Luz"
Es un Arte, es una ciencia y una practica.
La fotografía computacional es la suma de la camara fotgrafica mas el proceso de la imagen llevado a cabo por una computadora.
Un teléfono inteligente sintetiza esta suma.

La fotografía computacional combina varios elementos:

  • El computo
  • Los sensores digitales.
  • La optica moderna.
  • Actuadores electromecanicos.
  • Iluminacion Inteligente.
  • Estrategias para ESCAPAR de las limitaciones de las cámaras tradicionales a película.
   

Las antiguas cámaras a film nos imponían serias limitaciones.
  • Usos de quimicos y cuarto oscuro.
  • 12,24 o 36 fotos por rollo.
  • Gratificacion instantanea.
  • Sensibilidad del film.
La fotografia computacional habilita la imagen a:
  • Rango dinámico sin limite.
  • Variable:
    • Foco.
    • Profundidad de campo.
    • Resolución.
    • Iluminacion.
    • Reflectancia.
  • Soporta y amplia los medio de la fotografia.
En la fotografia computacional tenemos una camara generalizada y una iluminacion generalizada.
Por ejemplo podriamos iluminar la escena con un barrido de laser de distintos colores.
O cargar en un pryector multimedia una imagen de la escena y con esa imagen iluminarla en el caso de Mapping.

Imagen Digital

La Imagen digital es la representación numérica de un sector de espacio  con dos dimensiones (x e y), referidas como una función continua I(x,y) o expresada en forma discreta com I(i,j).
La resolución de una imagen se expresa con su alto y ancho.
Cada pixel (elemento de imagen consiste en la representacion numerica de la intensidad de la luz, para cada elemento de la imagen x e y y se representa por I(x,y).



Una disposicion de dos dimensiones de pixels puede ser representada mediante una Matriz.
Para una imagen en blanco y negro los valores de intensidad de luz pueden variar desde 0 =Negro a 255 = Blanco.
Computacionalmente se puede representar por un carácter sin signo de 8 bit (unsigned char 8 bit).


Una vez que tenemos la imagen representada matematicamente por una matriz podemos tomar medidas estadisticas de la Imagen. Una de las medidas mas usadas es el histograma sobre el eje horizontal (x) tenemos los valores de iluminacion por ejemplo de 0 a 255 y en el eje vertical y tenemos cuantas veces aparece ese valor en la Matriz o sea en la imagen.


Para las imagenes de color se dividen en 3 canales de color Rojo, Verde y Azul (Red, Green  y Blue RGB), cada pixel de la imagen tiene tres intensidades una para el Rojo otra para el verde y otra para el Azul.
La cantidad de bits que se usan para representar una imagen se llama profundidad de color.

  • 1 bit por pixel forman dos colores Blanco y Negro.
  • 4 bits por pixel forman 16 colores
  • 8 bits por pixel forman 256 colores
  • 24 bits por pixel forman 16.777.216 colores


Los formatos mas comunes para guardar las imágenes en archivos de computadoras GIF, JPG, PPM, TIF, BMP.
Ademas cada camara tiene un formato nativo que se llama RAW.

Leyendo y escribiendo Imagenes.

Para leer una Imagen desde un archivo en Python con la libreria OpenCV

img = cv2.imread(‘filename.EXT’);

Para escribir una Imagen a un archivo en Python con la libreria OpenCV
cv2.imwrite(‘filename.EXT’, img);


Necesitamos principalmente la siguiente informacion.
• dimension de la imagen, bits por pixel, orden de los canales de color.
• informacion de la compresion de la imagen
Metadata de la imagen (Exchangeable Image File Format: EXIF, etc.)

Manipulando imagenes digitales.


El siguiente programa separa una imagen en sus componentes básicos Rojo, Verde y Azul



import sys
import os
import numpy as np
import cv2

def split_rgb(image):
  '''Separar la imagen en sus canales rojo, verde y azul.
  
  image - una matriz  numpy  (fila, columnas, colores).
  output - tres matrices numpy (rows, columns) y dtype igual a 
           image, conteniendo los canales correspondientes. 
  
  Asegurese que el formato de salida tiene solo dos componentes!
  Por ejemplo, (600, 800) en lugar de (600, 800, 1)
  '''
  red = image[:,:,2]
  green = image[:,:,1]
  blue = image[:,:,0]
  return red, green, blue

def main():
  ''' Esta funcion aplica el script  a la imagen.

  Va a buscar imagenes en los subdirectorios imagesages/part0, y aplica la fucion split_rgb y guarda las imagenes resultantes.
  '''
  imagesfolder0 = os.path.abspath(os.path.join(os.curdir, 'images', 'part0'))
  print '''Buscando imagenes en {} subdirectorios
  (ignora imagenes con red, green, o blue en el nombre)'''.format(imagesfolder0)

  exts = ['.bmp', '.pbm', '.pgm', '.ppm', '.sr', '.ras', '.jpeg', '.jpg', 
    '.jpe', '.jp2', '.tiff', '.tif', '.png']

  for dirname, dirnames, filenames in os.walk(imagesfolder0):
    for filename in filenames:
      name, ext = os.path.splitext(filename)
      if ext in exts and 'red' not in name and 'green' not in name and \
        'blue' not in name:
        print "Separando imagen {}.".format(filename)

        img = cv2.imread(os.path.join(dirname, filename))
        red, green, blue = split_rgb(img)

        for values, color, channel in zip((red, green, blue), 
            ('red', 'green', 'blue'), (2,1,0)):
          img = np.zeros((values.shape[0], values.shape[1], 3), 
              dtype = values.dtype) 
          img[:,:,channel] = values
          print "Guardando  imagen {}.".format(name+color+ext)
          cv2.imwrite(os.path.join(dirname, name+color+ext), img)



if __name__ == "__main__":
  main()

No hay comentarios:

Publicar un comentario