Showing posts with label procesamiento de imágenes. Show all posts
Showing posts with label procesamiento de imágenes. Show all posts

Sunday, October 11, 2015

Introducción a los algoritmos de compresión de imágenes


En el curso que doy de Proceso Digital de Imágenes (PDI), es siempre importante hablar de un tema que muchas veces es difícil de abordar. Se trata del de la compresión de archivos, en particular, del de la compresión de imágenes, el cual en alguna medida permite que las mismas ocupen menos espacio en los medios de almacenamiento y mejor aún, que la transmisión de las imágenes y fotos sea más rápido. Por ejemplo, si puede reducir una imagen al 10% de su tamaño en bytes, pues puedo, en principio, enviar diez imágenes por el precio de una, para decirlo de manera coloquial. Así, la compresión ayuda muchas veces a ser más eficientes en lo que se refiere al uso del ancho de banda por Internet. Por otra parte, la compresión permite usar menos espacio de almacenamiento.

Hay básicamente dos esquemas usados en este tema:

  • Compresión sin pérdida de información (losseless)
  • Compresión con pérdida de información (lossy)


En la primera, la compresión y descompresión del archivo (para convertir la imagen comprimida y podamos verla), no pierde información del archivo original. Vamos, al descomprimir la imagen es estrictamente igual a la original. La segunda compresión, en cambio, pierde información y el efecto de comprimir quizás no lo note el ojo humano al descomprimir y mostrar la imagen, pero si vemos a detalle veremos que habremos perdido información de la imagen original.

Cabe decir que a cambio de ahorrar bytes en el archivo original de almacenamiento, la versión comprimida debe descomprimirse y eso finalmente lleva tiempo. En cómputo no existe ningún procedimiento ganar-ganar. Si ganamos en espacio perdemos en tiempo y viceversa. Esto es un buen ejemplo de ello.

Los esquemas de compresión de imágenes son variados y los más usados son JPG o TIFF. Hace unos años, más de 20, el formato PCX, del cual hablaré en otro artículo próximamente, era uno de los más usados y simples, pero cayó en desuso ante sofisticados esquemas de compresión como los que plantean TIFF o JPG.

Pensando en cómo ejemplificar la compresión de imágenes, como una primera aproximación al problema, se me ocurrió que podía reducir a una tercera parte cualquier imagen que estuviese en tonos de grises. La razón de ello es simple: en 24 bits de color tenemos 8 bits para el rojo, 8 para el verde y otros 8 para el azul. Así, tenemos más de 16 millones de posibles colores con combinación de bytes R,G,B, que es el modelo conocido precisamente como RGB. Pero en tonos de gris tenemos solamente 256 tonos posibles. Cada tripleta R,G,B contiene R=G=B, es decir, las componentes de color en RGB son idénticas entre sí. Por ello, tenemos el tono de gris más oscuro (el negro), como (0,0,0), un poco menos negro será (1,1,1), menos negro aún será (2,2,2) y así sucesivamente. El blanco será (255,255,255).

Si esto es así, una imagen en tonos de gris puede reducirse a la tercera parte de su tamaño original leyendo una sola componente (el R, el G o el B de cada pixel de la imagen) y escribiendo en un archivo de bytes esa componente de cada pixel en la imagen. La idea es muy simple de programar y el algoritmo es éste:


(dar click en la imagen para verla más grande)

Cabe decir que cuando tengo la imagen que voy a procesar, primero la paso a tonos de gris tomando las componentes R, G y B, sumándolas y dividiendo de manera entera entre 3, es decir:

Gris := (R + G + B) div 3;

Así me aseguro que la imagen es de tonos de gris. De hecho, al convertir de color a tonos de gris ya perdemos información de color de la imagen, pero en este caso no es el asunto que discutimos.

Ahora bien, ¿cómo podríamos mostrar la compresión lossy, que es donde sí se pierde información al recuperar la imagen comprimida? Una idea sencilla resultó ésta: Tomemos una imagen en color y entonces revisemos las componentes de color (R,G,B). Tomemos el Rojo, la R y listo, digamos que ése es el tono de gris. Por lo tanto la imagen final en cada pixel tendrá el componente (R,R,R) en donde había antes un (R,G,B). ¿Qué tanto podría cambiar la imagen original en blanco y negro usando solamente la componente R de cada pixel?

He aqui dos imágenes. La de la derecha es la imagen en tonos de gris original. La de la izquierda es utilizando solamente la componente R(ed) para formar el tono de gris.



Tonos de gris vs Lossy (usando la coordenada R)

La diferencia visual quizás no es muy notable, pero de alguna manera, si nos fijamos con cuidado, veremos que la imagen "lossy" es un poco más oscura. Si en lugar de usar la componente R usáramos la B, encontraríamos un resultado "lossy" más obvio:


Tonos de gris vs Lossy (usando la coordenada B)

De hecho, se me ha ocurrido hacer un experimento más: Tomemos la imagen original en tonos de gris y saquemos los tres componentes de color, R, G y B, tomando uno de ellos al azar para formar el pixel correspondiente como (R,R,R), (G,G,G) o (B,B,B). Tal vez así, al elegir consistentemente el R, el G o el B de forma que se distribuyan esos tonos de gris formados con una sola componente, el resultado final podría ser mejor. Hice la prueba, pero me llevé una sorpresa inesperada:



Tonos de gris vs Lossy al azar (entre coordenadas R,G y B)

En resumen, usar una sola componente parece que no es tan descabellado si es que usamos la componente R o la G. Con la componente B la descompresión si muestra que se ha perdido mucha información de la imagen original. Probablemente la coordenada R sea la mejor opción en este caso.

El esquema mostrado reduce las imágenes a un 33% del tamaño original, lo cual quizás no puede considerarse malo, peor por ejemplo, esta misma imagen en JPG se reduce dos veces lo que podemos lograr con esta idea.

Aún así, no hay ninguna mejora con respecto al tamaño de la imagen comprimida. Digamos que es independiente de la componente elegida aunque para fines ilustrativos, usar el tono de gris calculado antes de procesar la imagen nos da una imagen resultante en donde no se pierde información de la imagen original.

Quien quiera mi programa de demostración, pídamelo a morsa@la-morsa.com y a vuelta de correo lo recibirá de manera gratuita.

Wednesday, April 10, 2013

El efecto AT&T y un nuevo reto de la programación lúdica

En 1988 Gerard Holzmann escribió un interesante libro sobre procesamiento de imágenes: "Beyond Photography - The Digital Darkroom". Pocos años antes, el autor trabajó con Rob Pike, Dennis Ritchie, Ken Thompson, entre otros, en los Laboratorios Bell, que a la postre lo adquiriera la empresa ATT. Debe haber sido fascinante interactuar con toda estas gente que trabajaba en tecnología con una pasión desbordada. Ahí nació, por ejemplo, el sistema Unix y el lenguaje C, que no son poca cosa. Hasta donde recuerdo, los Laboratorios Bell tenían a 8 premios Nobel entre sus empleados.



El libro de Holzmann se puede conseguir en Amazon, pero nuevo cuesta 133 dólares. Hay copias usadas por unos 10 dólares. Sin embargo, el propio autor ha puesto una copia en pdf de forma gratuita, y que puede consultarse aquí.

En dicha obra, el el capítulo 4, Holzmann se dedica a experimentar con diferentes filtros gráficos. Muchos de ellos eran meros experimentos bajo la premisa "a ver qué pasa si aplicamos esta ecuación sobre la imagen". Y probablemente muchos de esos experimentos no fueron publicados. Sin embargo, uno de ellos me pareció interesante. Cito al autor en la página 42: "Por alguna razón, el retrato de Peter Weinberg siempre fue el objetivo principal en nuestro experimentos de edición de imágenes.  Todo empezó un par de años antes cuando Peter ascendió a jefe del departamento y a su notoria distracción de dejar su cuadro con su imagen en cualquier parte. Una tarde de sábado, que estábamos bromeando, Rob Pike y yo empezamos a hacer fotocopias de dicha fotografía de Peter, enfatizando la jerarquía administrativa existente cuando preparábamos una gráfica de la estructura de los Laboratorios Bell. Jugando poníamos a Peter en todos los posibles puestos. El propio Peter pronto se dio cuenta de esto y debe haber llegado a la conclusión de que lo mejor que podía hacer era no reaccionar a este asunto. Así al menos él esperaba que su imagen no fuese aparecer magnificada en alguna de las torres de agua del Laboratorio. No obstante, la foto de Peter aparecía y desaparecía en los lugares más extraños.

Un par de semanas después de que ATT revelara el nuevo logotipo corporativo, Tom Duff hizo una imagen de Peter al estilo de dicho logo y se convirtió en el símbolo de nuestro centro de trabajo. Rob Pike mandó hacer camisetas con la foto "ATT-izada" de Peter y Ken Thompson ordenó tazas de café con el logo de Peter. E inevitablemente el 16 de septiembre de 1985 apareció el logo de Peter en una de las torres de agua".

¿Cómo se pueden hacer imágenes de las personas basadas en el logotipo de ATT? Aparentemente Duff fue el autor del filtro y Holzmann no indica cómo se hizo. En consecuencia, hubo que partir de cero información. Consideremos la imagen original y el resultado mostrado por Holzmann:



El logo de ATT es éste:


A partir de esto es claro que las imágenes deben ser de blanco y negro estrictamente. La solución es pues una combinación de filtros. He aquí los pasos a seguir:

  1. Tómese una imagen
  2. Si es de color, pásese a tonos de gris
  3. Ya en tonos de gris, aplíquese el filtro alto contraste
  4. A esa imagen resultante, aplíquese el filtro ATT

Pasar a tonos de gris una imagen es uno de los filtros más comunes. En una imagen en tonos de gris tenemos que cada pixel tiene en sus componentes R=G=B, es decir, la tripleta (Rojo, Verde, Azul) (o (R,G,B) por sus siglas en inglés), tiene los mismos valores. Las imágenes de tonos de grises contienen a lo más 256 tonos diferentes (de (0,0,0), el negro, al (255,255,255) el blanco). Aquí hay dos formas de hacer esta transformación, usando para cada pixel una de las dos posibles ecuaciones:

(1) Gris = (R + G + B) / 3
o
(2) Gris = (0.30 * R) + (0.59 * G) + (0.11 * B)

Ahora bien, una vez teniendo la imagen en tonos de grises, aplicar un filtro alto contraste es fácil. Se recorre la imagen pixel por pixel. Se calcula el número de color, el cual se basa en la siguiente fórmula:


Número de color = (65536 * R) = (256 * G) + (B)

donde las componentes en el modelo R,G,B son: R el componente en rojo, G el verde y B el azul. Si éste número de color es mayor de 8 millones, entonces ponemos un color blanco. Si es menor de ese número, ponemos un color negro. Así, una imagen en tonos de grises se transforma en una imagen en blanco y negro, como en el siguiente ejemplo.


Y ahora está el problema de crear la imagen usando un filtro “ATT alike”. Pero aquí no diré cómo hacer esto (hasta que acabe el reto). Cuando aparezcan los resultados explicaré el filtro a detalle. Es decir, parte del reto es discurrir cómo se puede hacer un filtro de esta naturaleza y no sólo seguir la descripción que pueda hacer yo del mismo. Así pues, el reto tiene este giro adicional, con respecto a retos anteriores.

Los resultados fueron bastante satisfactorios y además, el software crea este tipo de imágenes de forma relativamente rápida. Por ejemplo, he aquí la imagen procesada con regiones de 9 pixeles y otra con regiones de 20 pixeles. Mientras más pixeles por región, más anchas son las franjas oscuras. ¿Cuál de los dos resultados le gusta más?
                 9 pixeles                             20 pixeles

Considerando todo esto, el siguiente reto de la programación lúdica es hacer el filtro ATT. En este caso no se describe cómo funciona ese filtro ATT y el programador que participe debe hallar cómo generar dicho filtro. Es decir, se complica un poco más el asunto, pues la descripción del filtro no se da. Cada quien tendrá que hallarla. Así pues, este reto es aún más complejo que el del filtro óleo.

He aquí las bases adicionales del reto:

  • Ganará el programa que transforme la imagen de Peter Weinberger (que aparece más abajo), en el menor tiempo posible. El segundo mejor tiempo obtendrá el segundo lugar. Desde luego, el resultado debe estar de acuerdo con la definición del filtro ATT del cual hemos hablado.
  • Habrá dos lugares: Ambos se llevarán una taza con el logotipo de La_Morsa. Mi intención es que al imprimir esas tazas aparezca una leyenda con el título de la misma y el lugar obtenido, para que quede constancia por el tiempo de vida de la taza.
  • Los programas pueden hacerse en cualquier lenguaje de propósito general y no se vale usar en éste particularmente, bibliotecas que hagan filtros gráficos. Los programadores tienen que resolver el problema por sí mismo, sin ayuda de bibliotecas externas. (Desde luego, se vale usar alguna biblioteca para cargar/guardar la imagen de Weinberger para procesarla, la cual es un JPG, pero nada más). Así pues, C, C++, C#, Pascal (Delphi), Javascript, Python, Ruby, Visual BASIC, Visual C, Java, etcétera, son idóneos para esta labor.
  • Los autores de los programas deberán mandar el código fuente y el archivo ejecutable en Windows 7.
  • Un autor puede mandar versiones mejoradas de su propio software dentro del tiempo del concurso. No se tomarán en cuenta las que se salgan del tiempo establecido.
  • En la medida de lo posible, el programa debe indicar el tiempo total del proceso realizado para crear la imagen tipo logo de ATT de Weinberger
  • El autor debe enviar el código fuente y quienes ganen aceptan que su código quede accesible para quien lo quiera ver.
  • Los programas deben poderse ejecutar en el sistema operativo Windows 7 de 32/64 bits. Se correrán en una máquina AMD con 6 núcleos y los resultados obtenidos son inapelables y definitivos. De nuevo aclaro: este es un reto de buena fe y no un concurso estrictamente. Los premios son meramente un estímulo extra para que se animen a entrarle al reto. Evidentemente asumo que el código de cada concursante es creación del mismo y que no andan copiando el código de otras partes, foros, sitios en Internet, etcétera. En caso de hallar que el código fue copiado, el programador queda descalificado.
  • El reto dura una semana a partir del día de la publicación del artículo. Por ejemplo, si éste se publica un 10 de mayo a las 3 de la tarde, el reto se cierra el 17 de mayo a esa misma hora.
  • Cuando reciba algún programa participante en el reto, le enviaré un acuse de recibo para asegurarnos que están todos los que son y son todos los que están.
  • El concurso es para quienes viven en la República Mexicana. Si alguien de otro país quiere participar es bienvenido, pero no podrá acceder a los premios (puede haber excepciones).
  • Los programas deben ser enviados a morsa@la-morsa.com o en su defecto a lopem@hotmail.com, por si alguna de las direcciones no funciona.
Así que queridos y entusiastas programadores, a entrarle al reto. Afilen sus herramientas de programación y que gane el mejor.

Imagen a procesar:


A quien le interese el filtro ATT, puede pedírmelo a morsa@la-morsa.com y a vuelta de correo lo recibirá sin costo alguno.

Wednesday, February 27, 2013

Generador de fotografías antiguas


La fotografía tuvo un balbuceante inicio. Las primeras fotografías, si mal no recuerdo llamadas daguerrotipos, eran de pésima calidad, en blanco y negro. La razón de esto es que no se sabía lo que hoy sabemos de química y de N productos químicos que permiten impresión en color, con una gran resolución si se necesita. Hoy, ya en el siglo 21, la fotografía ha evolucionado a grados insospechados y no es para asustar a nadie que se puedan conseguir cámaras de 16 megapixeles por unos cuantos cientos de dólares.

Así pues, hay un largo camino desde las primeras fotografías a las que se pueden hacer actualmente. Hace no muchos años, en el tiempo en donde aún no se podían conseguir cámaras digitales, era común que la gente fuese a establecimientos específicos de fotografía, a imprimir sus placas. Con la llegada de las cámaras digitales, el esquema cambió. Ahora todas las imágenes pueden verse en la computadora y para imprimirlas, pues usamos papel normal e impresoras de colores, ya sean de inyección de tinta o laser. Hay, desde luego, papeles fotográficos, que dan mucha más calidad a las fotografías digitales, pero es claro que esto es más costoso y es para un público muy especializado.

El tiempo en el que la gente común y corriente mandaba a imprimir sus fotografías a establecimientos dedicados a esto han pasado. Ya de hecho prácticamente no existen y quienes tengan fotografías de ese época verá con cierta nostalgia que los colores van cambiando. El paso del tiempo hace que en cierta medida se pierda brillantez en las fotos impresas. Si nos remontamos a más años en el pasado, veremos que las fotografías en blanco y negro pasan a decolorarse y adquieren un color sepia.

El Programa

Pues bien, el Generador de fotografías antiguas hace precisamente esto: convierte una imagen digital en su equivalente en sepia, como si hubiesen pasado muchos años sobre esa foto. El efecto es interesante y realmente sencillo de hacer.

El programa requiere una fotografía en color o blanco y negro digital, es decir, un archivo BMP o JPG. Una vez cargada ésta al software, se puede cambiar un parámetro que permite hacer más o menos sepia la imagen. Al oprimir la opción de Procesar, el sistema mostrará la imagen avejentada, en color sepia, como si le hubiesen caído los años encima.

El programa permite grabar el resultado final en un archivo JPG.

La imagen aparece distorsionada en la pantalla si es más grande que la que el software presenta, pero puede eliminarse la distorsión usando la opción 'stretch', que es una especie de interruptor, que se apaga o se prende, llamándolo una y otra vez.

Es un programa sencillo, que técnicamente implementa el filtro sepia.

A quien le interese puede pedírmelo a morsa@la-morsa.com y se lo mandaré de forma gratuita a vuelta de correo.