[MÚSICA] [MÚSICA] Hola, en esta ocasión vamos a ver el visor de imágenes para ver cómo operar con arreglos en dos dimensiones, con matrices. Comencemos con la descripción, se quiere construir una aplicación que permita la visualización de imágenes en formato BMP. Formato BMP consiste en guardar la información del color de cada pixel que conforma la imagen. El color de un pixel está representado en el sistema RGB, rojo, verde y azul, red, green, blue. En el cual el color se forma de la combinación de estos tres componentes, cada uno de los cuales representados por un número que indica la proporción del color del componente en la imagen, en el color final. La aplicación se mostrara una imagen que puede ser de 400 pixeles por 300 pixeles al cargarla y que permite ofrecer seis métodos de transformaciones, transformar a negativo. Para calcular negativo se toma el color negativo de cada pixel, es decir, a cada componente por cada pixel se le resta 255 y se toma el valor absoluto de dicha resta, aquí está el resultado. Flip vertical,que sirve para invertir verticalmente la imagen, para eso se cambian las columnas de pixeles de la imagen, la primera con la última, la última es segunda, etcétera, etcétera. Entonces, si vemos aquí la imagen, el árbol grande, por ejemplo, que se encuentra en esta posición. Tras hacerle un flip vertical va a estar en esta posición. Binarización, consiste en llevar los colores de las imágenes a dos colores, negro y blanco, o estableciendo un umbral y los pixeles que estén por debajo o por encima se cambian por blanco o se cambian por negro de acuerdo a si están por debajo o por encima. En este caso, el umbral es el promedio de la imagen y para calcular con el promedio, se promedia cada uno de los componentes. Entonces, por ejemplo, si se utiliza 122 el umbral en la escala en blanco y negro sería este. Los otros tres métodos, que son pixelamiento, escala de grises y convolución no los vamos a ver en detalle porque queremos solo para propósitos de este caso de estudio, implementar los tres primeros. Miremos rápidamente el modelo conceptual, diagrama de clases, vemos que hay un relación con la clase color que es la clase de Java que representa un color en sus componentes RGB, y la imagen que tiene el ancho, el alto, así como otros operadores. Bien, solo hay una clase entonces nuevamente no nos interesamos por la interfaz, vamos directamente al mundo. Tenemos el ancho, el máximo, Tenemos una matriz de elementos de tipo Color, de Java, que son obviamente elementos, son objetos que tienen componente RGB dispuestos en la matriz de nuestro mapa de bits. Entonces, vamos a implementar-- primero intentemos correr la aplicación, si nos damos cuenta por ejemplo ni negativo, ni reflejar, ni binarización por más que le demos un umbral, funciona, no obstante pixeles, escala de grises y convolución debería funcionar. Entonces, vamos a observar y vamos a agregar los métodos que hacen falta. Entonces, convertir negativo, recordemos que para convertir en negativo tomamos el valor absoluto del resultado de restarle a cada componente de cada pixel 255. Entonces, vamos a recorrer la matriz. Para recorrer una matriz acordémonoss que tenemos que utilizar dos ciclos, uno definido por el alto y otro definido por el ancho utilizando dos variables de índice, que nos indican el índice o la posición actual de manera diferente y a partir de eso, entonces simplemente decimos, por ejemplo, color, vamos a tener el color original. Entonces el mapa de bits, vamos a pedirle el color, la posición I, J y vamos a tener un color entonces aquí guardado y vamos a generar los nuevos colores. Entonces, por ejemplo sabemos que esos son enteros. Entonces, el nuevo rojo va a ser igual al valor absoluto del color original. Pedimos la componente roja, give red menos 255. Hacemos lo mismo para el verde y para el azul. Entonces, a ver, verde y azul. En este caso, pedimos el verde, pedimos el azul y lo que hacemos es que a nuestro mapa de bits en la posición I, J, vamos a remplazarlo por un nuevo color que va a tener como componentes RGB las que acabamos de calcular. Tenemos ya nuestro primer método, un doble ciclo que nos permite justamente recorrer primero columna y luego ir de acuerdo al ancho por fila-- cuadro a cuadro por una fila. Y vamos cambiando cada color de manera sencilla. Ahora vamos a ver un método que refleja la imagen, entonces vamos a recorrer y vamos a intercambiar columna por columna. Entonces, en este caso hacemos lo mismo, realizamos los dos ciclos que nos permitan recorrer la matriz J igual a cero, J menor que el ancho, J++, a veces podría sucedernos que podríamos poner KI++ por accidente. Es importante verificar que hayamos puesto la variable de control del ciclo de manera adecuada y que no hayamos cometido ningún error y vamos a guardar una variable que se llame "temporal" con el color que está en la posición I, J, y vamos a intercambiar entonces el color que está en la posición I, J, lo vamos a intercambiar con el que está en la columna que está del otro lado. En este caso, sería I, y ancho menos J, menos 1, para poder hacernos adecuadamente. Recordemos, entonces que el ancho-- obviamente la última variable va a ser el ancho menos 1 si tenemos de ancho máximo 400. En este caso, recordemos que nuestra matriz llegará hasta 399 y si queremos cambiar por ejemplo cuando J igual a cero, entonces sería 399, o sea, ancho menos 0, menos 1, porque sino estaríamos cambiándolo con 400 y esto nos daría un error. Finalmente, hacemos el intercambio, entonces de la última, que acabamos de ver menos J, menos 1, por el color que guardamos de la posición temporal y acabamos ¿o no? Bueno, si nos hemos dado cuenta aquí tenemos un error, resulta que cuando lleguemos del otro lado vamos a volver a intercambiar el valor. En particular, nos vamos a dar cuenta que estaremos intercambiando las últimas columnas y volveremos a tener exactamente la misma imagen porque ya habiendo pasado de la mitad, empezaremos de nuevo a reintercambiar las columnas, dejándolas en su posición original. ¿Qué tenemos que hacer? Simple, solamente vamos hacer este recorrido la mitad del tiempo. Es decir, solo hasta que lleguemos a la mitad de la imagen porque una vez lleguemos a la mitad ya habremos hecho el trabajo para la otra mitad a través del intercambio. Es decir, solo tenemos que recorrer la mitad de las columnas y con esto hemos acabado. binarizar imagen que recibe un umbral. En este caso, entonces tendremos que recorrer toda la imagen y obtener un promedio recordemos, y si el promedio está por debajo del umbral, mandamos el pixel a blanco, de lo contrario lo mandamos a negro. Entonces, hagamos lo siguiente, vamos hacer el recorrido por cada uno I menor que alto, I++. Hacemos lo mismo para J, J menor que ancho, J++, y ahora vamos a pedir el color del pixel. Entonces, hacemos hacemos la petición a la matriz para que nos del color en la posición I, J, y calculamos el promedio. Entonces, el promedio-- Vamos aproximar a un entero. Entonces va a ser igual al azul, al componente azul, más el componente verde, más el componente rojo y como es un promedio, entre tres, aquí se me olvido un pequeño igual. Asignamos el valor este y lo que vamos hacer es lo siguiente, es una discriminación binaria. Entonces, si el promedio resulta ser menor que el valor que recibimos del umbral, entonces simplemente mandamos éste valor a negro, entonces new color, cero, cero, cero. De lo contrario, entonces no necesitamos verificar porque solo hay dos posibilidades y si no es una es la otra, es decir si es mayor al umbral, lo enviamos a blanco, en blanco sería 255, 255, 255. Bien, revisemos entonces qué tal están nuestros métodos. Primero negativo, en negativo recordemos que fue el primero que implementamos y deberían darme los colores en negativo. Tenemos un problema, Así que vamos a revisar nuestra implementación. Estamos reemplazando bien los colores, pero si nos dimos cuenta acá hicimos mal una asignación, esta asignación es en la posición "I" como "J". Es importantísimo llevar bien la referencia de ambas variables para evitar cometer errores tan sencillos, como dijimos bitmapping "J,J" simplemente cambió los colores en la diagonal, así que volvamos a intentarlo, negativo y perfecto, está funcionando a la perfección. Vamos a correrlo otra vez para usar la imagen original, vamos a reflejarla, perfecto, no hay ningún problema y podemos binarizarla. Entonces, utilicemos más o menos la mitad de los colores para ver, el umbral va a ser más o menos la mitad de 255 para ver qué colores nos da, y perfecto, funciona a la perfección. Vamos a hacer un pequeño experimento antes de acabar esto, este caso de estudio, ahora imaginemos que quisiéramos reflejar la imagen pero verticalmente, es decir que en lugar de intercambiar columnas intercambiáramos filas. En éste caso, lo haremos hasta la mitad de los saltos y los J van a permanecer constantes, todo el tiempo, pero lo que sí debe cambiar es esta posición, entonces nuevamente sería, "alto menos 1 menos I", porque si fuese "J" sería para las columnas, en éste caso es para las filas y lo mismo acá. Recordemos entonces como la última fila es realmente "fila menos 1", tenemos que tener siempre en consideración eso, vamos a ver si nuestro reflejo rápido funcionó, perfecto, ahora la reflejamos de manera vertical, haciendo un cambio. Bien, esto acaba nuestro caso de estudio del visor de imágenes, esperamos que hayan quedado claros los conceptos de recorridos sobre matrices y los esperamos para los próximos casos y les deseamos también suerte con los ejercicios. [MÚSICA]