Podcast: Descargar (23.0MB)
El tratamiento digital de imágenes es un campo muy en auge desde hace ya mucho tiempo en informática, en este capítulo veremos el tratamiento de imágenes con JavaScript. Es un área muy extensa que puede abarcar desde los simples retoques fotográficos, hasta la detección de objetos en la visión artificial. En su día ya hablamos de la realidad aumentada y la realidad virtual, dos técnicas muy ligadas al tratamiento digital de imágenes.
Pero antes de nada ya sabéis que tenemos una cuenta en Twitter y en Facebook donde nos podéis seguir. También hay un formulario de contacto a vuestra disposición para cualquier duda, sugerencia o petición, solo tenéis que rellenar vuestro nombre, el e-mail y la consulta. Por otro lado la lista de distribución está esperando vuestra suscripción.
Quizás la vista sea el sentido más complicado de poder imitar en términos informáticos. Aunque hay multitud de estudios sobre el tema, quien se encarga de procesar las imágenes que capta el ojo humano es el cerebro, esa máquina imposible de replicar. Cuando nuestros ojos captan una imagen es capaz de procesar tanta información que podemos reconocer objetos en condiciones de iluminación pobres y a grandes distancias. Eso es debido a la información que hay almacenada en nuestro cerebro, es como si fuera una base de datos la cual consultamos miles de veces por segundo para recordar qué objeto es el que estamos viendo. En la actualidad no existe una técnica ni tecnología que se aproxime a como vemos los seres humanos, ni incluso los animales. Es cierto que la ciencia avanza a pasos agigantados pero en el campo de la visión artificial aún queda mucho camino por recorrer. En la actualidad existen innumerables aplicaciones donde se utiliza el tratamiento digital de imágenes tanto en la sociedad de consumo (televisión digital, telefonía móvil, videojuegos, etc…) como en el sector industrial y de servicios (inspección, robótica, medicina, etc…).
En este capítulo os voy a hablar de cómo podemos comenzar con el tratamiento digital de imágenes. Lo primero que tenemos que tener claro es que existen dos tipos de imágenes digitales, imágenes vectoriales e imágenes de mapas de bits.
Las imágenes vectoriales son aquellas que tienen fórmulas matemáticas complejas que definen su contorno y relleno. Esto posibilita que este tipo de imágenes sean escalables sin perder calidad. Estas imágenes no son objeto de este artículo.
Por otro lado existen las imágenes de mapas de bits, son las que están descritas por un conjunto de celdas llamados píxeles. Cada píxel contiene información de un color. En la siguiente imagen podemos ver como haciendo zoom podemos llegara a ver los píxeles. Al final una imagen de mapa de bits es una cuadrícula donde cada píxel contiene un color.
Antes de seguir viendo más en profundidad de que está compuesta una imagen hay que dejar claro ciertos conceptos. Ya hablamos en su día de los megapíxeles y la gran mentira que hay detrás de ellos así que, no hablaremos de este concepto pero si que os voy a hablar de que es la resolución de una imagen, dimensiones de píxel y la profundidad de píxel.
Resolución de una imagen
La resolución de una imagen nos da información de la cantidad de píxeles que la describen. Se suele medir en píxeles por pulgada (ppi del inglés pixels per inch) y nos indica la cantidad de píxeles que caben en una pulgada. La pulgada es una medida inglesa que equivale a 2,54 cm, para que todos nos entendamos, serían los píxeles que caben en 6,45 cm². Este concepto es muy importante ya que determina la calidad y el tamaño que va a ocupar una imagen. La resolución normal que se utiliza en Internet es 72 ppi, esto nos indica que en 2,54 cm² hay 72 x 72 píxeles, osea 5.184. Si aumentamos la resolución tendremos más píxeles por pulgada y por lo tanto tendremos más información, más calidad y ocupará más nuestra imagen.
Dimensiones de píxel
Las dimensiones de píxel nos da información del tamaño de la imagen. Este tamaño viene expresado en número de píxeles horizontales y número de píxeles verticales. Imaginaros que queremos escanear una imagen de 254 cm x 254 cm (equivale a 100 pulgadas x 100 pulgadas), a una resolución de 150 ppi. Queremos saber en términos de dimensiones de píxel cual va a ser su tamaño, lo único que tenemos que hacer es multiplicar el ancho y el alto de la imagen impresa por la resolución. Nos daría una imagen de 15.000 x 15.000 px.
Profundidad de píxel
La profundidad de píxel o también llamada profundidad de color nos proporciona la cantidad de información de color que puede almacenar cada píxel en bits. Esto quiere decir que si tenemos una profundidad de píxel de 1, podremos almacenar 2 elevado a 1 valores posibles o sea 2 valores. Estas imágenes se llaman binarias y cada píxel puede ser blanco 0 o negro 1. A continuación os muestro una tabla con la profundidad de color donde podemos ver diferentes tipos de archivos.
Profundidad (bits) | Color | Formato |
1 | 22 = 2 colores | GIF, BMP |
8 | 28 = 256 colores | GIF, BMP |
16 | 216 = 65.536 colores | BMP, TGA, TIF, PNG |
24 | 224 = 16.777.216 colores | BMP, TGA, TIF, JPG |
Una vez tenemos claro los conceptos de resolución de imagen, dimensión de píxel y profundidad de píxel podemos pasar a describir el color. Como ya me imagino que estáis intuyendo, el color esta estrechamente ligado a la profundidad de píxel.
No es más que un haz de luz con una longitud de onda que se refleja en un objeto y nuestro ojo es capaz de interpretar un color. El color que percibimos a través del sistema visual se puede expresar numéricamente mediante fórmulas matemáticas. De este hecho surgen los modelos de color. Los más importantes son RGB (Red, Green, Blue), CMYK (Cyan, Magenta, Yellow, Key), HSV (Hue, Saturation, Value) y CIELAB (CIE 1976 L*a*b*).
Nos centraremos en el modelo de color RGB. Este modelo de color es el utilizado por todos los sistemas audiovisuales y se conoce también como sistema aditivo ya que con la mezcla por adición de los tres colores primarios podemos representar los demás colores.
Haciendo un resumen de lo que hemos visto hasta ahora, tendremos una imagen que está formada por celdas de una matriz y dentro de cada celda tendremos 3 números que corresponden con los colores R (Rojo), G (Verde) y B (Azul).
125 10 32 | 210 34 43 | 210 34 45 | |||
23 156 0 | 2 67 32 | 120 88 90 | |||
67 89 187 | 45 167 32 | 12 120 0 | |||
56 210 92 | 127 120 32 | 32 54 189 | |||
200 2 121 | 189 237 32 | 156 90 233 |
JavaScript
Ya tenemos la información suficiente para poder trabajar con imágenes en JavaScript. Para este efecto tenemos el método que nos ofrece el elemento Canvas getImageData(). Con este método seremos capaces de extraer la información a nivel de píxel de una imagen y recorrerlo a través de un bucle. Este método nos devolverá un array de una dimensión del siguiente estilo:
[120][2][4][255][45][67][89][255][210][214][17][255]
Esto son los píxeles de nuestra imagen pero, entendamos un poco como podemos agruparlos. Este método nos devuelve por cada píxel cuatro componentes RGBA, los tres colores primarios R (rojo), G (verde), B(azul) y una nueva componente A (Alpha), que nos permite cambiar la transparencia de dicho píxel. Así que en el ejemplo anterior tenemos tres píxeles que serían los siguientes:
[120][2][4][255] -> Píxel 1
[45][67][89][255] -> Píxel 2
[210][214][17][255] -> Píxel 3
El rango de valores que puede tener cada componente son de 0 a 255 por lo tanto la profundidad de píxel es de 8.
Ya podemos comenzar a tratar una imagen y lo más básico o fácil sería convertir una imagen a escala de grises. Esto consiste en obtener el tono de gris de cada píxel. Para obtenerlo hay que hacer la media de las componentes de color. Esta media debe ser algo especial ya que debemos obtener la luminancia en escala de grises para que coincida con la luminancia del color. El ser humano no es igual de sensible a todos los colores, es más sensible al color verde que el color azul así que esta media debe ser ponderada a través de una formula matemática más que probada. Si no hiciéramos esta ponderación, la media sería sumar todas las componentes y dividir por 3 (R+G+B)/3 = color gris, que sería lo mismo que multiplicar a todas las componentes por 0,33. En cambio vamos a realizar la ponderación de la siguiente manera, al ser más sensible el ojo humano al verde lo vamos a multiplicar por 0.52, al rojo por 0.33 y al azul por 0.15.
R*0.33+G*0.52+B*0.15 = color gris
Aplicando esta ponderación al ejemplo anterior tendríamos el siguiente resultado
[120][2][4][255] => 120*0.33+2*0.52+4*0.15 = 41 -> Píxel 1
[45][67][89][255] => 45*0.33+67*0.52+89*0.15 = 63 -> Píxel 2
[210][214][17][255] => 210*0.33+214*0.52+17*0.15 = 183 -> Píxel 3
Transformar a escala de grises es solo un ejemplo de todo lo que podemos hacer con el tratamiento de imágenes, suavizar una imagen, realzar, obtener bordes, filtrar por colores, incrustar marca de agua, etc…, todo esto lo iremos viendo con más artículos en nuestro blog y con fragmentos de código que iremos incorporando.
Bueno pues hasta aquí esta pequeña introducción al tratamiento digital de imágenes donde hemos visto los conceptos básicos para poder trabajar a nivel de programación con una imagen digital. Aquí os dejo un fragmento de código donde podemos ver cómo convertir una imagen a escala de grises con JavaScript.
A continuación los enlaces de los que hemos hablado en este podcast.
Recurso del día
CamanJS es una librería escrita en JavaScript que nos permite manipular imágenes aplicando filtros y efectos de una forma rápida. Combina una interfaz fácil de usar con técnicas de edición de imágenes avanzadas y muy eficientes. Aunque incorpora una amplia gama de funciones de edición de imágenes, se puede extender con nuevos filtros y plugins. Es una librería totalmente independiente y funciona tanto en el navegador como en servidor, con NodeJS.
Muchas gracias a todos por los comentarios y valoraciones que nos hacéis en iVoox, iTunes y en Spreaker, nos dan mucho ánimo para seguir con este proyecto.