ESQUELETIZADO DE IMAGENES CON PYTHON Y SCIKIT-IMAGE.

Destacado

El procesamiento de imágenes es una disciplina fascinante que abarca una amplia gama de técnicas para manipular imágenes digitales con el fin de mejorar su calidad, extraer información relevante o realizar tareas específicas. Una de estas técnicas es el esqueletizado de imágenes, que tiene aplicaciones en diversas áreas, como visión por computadora, reconocimiento de patrones, análisis de formas y más. Concretamente consiste en un proceso en el que se reduce una forma binaria a su representación más esquemática, manteniendo la topología de la forma original. Esencialmente, el esqueleto de una imagen representa la «columna vertebral» de la forma, conservando su estructura esencial. Esta técnica es útil para simplificar la representación de formas y facilitar la extracción de características relevantes.

En este artículo, exploraremos en detalle la utilidad del esqueletizado de imágenes y cómo se implementa en Python utilizando la biblioteca ‘scikit-image‘ la cual deberemos instalar previamente en nuestro sistema con ‘pip install scikit-image‘:

IMPLEMENTACION EN PYTHON:

La mencionada biblioteca ‘scikit-image‘ proporciona una implementación eficiente y fácil de usar del esqueletizado de imágenes a través de la función skeletonize. Esta función toma una imagen binaria como entrada y devuelve el esqueleto de la forma representado como una matriz binaria. A continuación, veremos un ejemplo de cómo implementar el esqueletizado de imágenes en Python utilizando dicha librería aplicada a la siguiente imagen:

Así el primer paso que deberemos dar es naturalmente el de importar las librerías y recursos a utilizar y proceder al cargado y lectura de la imagen en cuestión con ‘OpenCV‘. En este punto usaremos la función ‘imread()‘ pasándole como primer argumento, la ruta a la imagen en cuestión y como segundo argumento, el valor 0, con lo que estaremos indicando que queremos cargarla en escala de grises:

Hecho esto y teniendo en cuenta que la operación que queremos realizar, ha de efectuarse sobre una imagen binaria, el siguiente paso será realizar dicha conversión mediante la aplicación de los correspondientes umbrales. En ocasiones puede ser útil la aplicación de inversión sobre la misma. Usándose en este caso la función ‘bitwise_not()‘:

Una vez realizados estos pasos previos, llevaremos a cabo la operación de esqueletización con ‘scikit-image‘ y su función ‘skeletonize()‘:

Finalmente mostraremos el resultado final, junto al original en gris y su versión binaria invertida, utilizando la función para visualizar fotos de ‘OpenCV‘, ‘imshow()‘:

OUTPUT:

CONCLUSION:

El esqueletizado de imágenes es una técnica poderosa en el campo del procesamiento de imágenes, con aplicaciones en diversas áreas como análisis de formas, extracción de características, reconocimiento de patrones y más. La implementación de esta técnica en Python utilizando la biblioteca ‘scikit-image‘ proporciona una forma eficiente y flexible de realizar operaciones de esqueletizado en imágenes digitales. Al comprender la utilidad y la implementación del esqueletizado de imágenes, los practicantes de procesamiento de imágenes pueden aprovechar esta técnica para una variedad de aplicaciones prácticas y proyectos de visión por computadora.

Saludos.

ENTRENANDO MODELOS PARA CLASIFICACIÓN DE IMAGENES CON PYTHON Y ‘TensorFlow’.

Destacado

En el mundo de la inteligencia artificial y el aprendizaje automático, la clasificación de imágenes es una tarea fundamental. Clasificar imágenes puede implicar identificar objetos, reconocer patrones o incluso diagnosticar enfermedades basadas en imágenes médicas. En este artículo, exploraremos cómo utilizar Python junto con ‘TensorFlow‘, una de las bibliotecas de aprendizaje automático más populares, para entrenar modelos de clasificación de imágenes de manera efectiva. La explicación la dividiremos en cinco sencillos pasos:

INSTALACIÓN DE TENSOR FLOW:

Aunque para nuestro ejemplo vamos a utilizar la plataforma de ‘Google Colab‘ (en donde no es necesaria esta acción) conviene saber como podemos instalar la librería localmente en nuestro sistema. Para ello podremos utilizar el comando ‘pip‘ al que estamos acostumbrados:

PREPARACIÓN DE LOS DATOS:

El primer paso en el entrenamiento de un modelo de clasificación de imágenes es preparar los datos. Para este ejemplo, utilizaremos el conjunto de datos ‘MNIST‘, consistente en una colección de imágenes de dígitos escritos a mano. ‘TensorFlow‘ proporciona, aquí, funciones para cargar y pre-procesar dicho conjunto de datos:

Así, empezaremos a elaborar nuestro modelo, importando la librería ‘TensorFlow‘. Tras ello, cargamos los datos de imágenes MNIST utilizando la función ‘load_data()‘ para después normalizar estos dividiendo los valores de píxeles de las imágenes por 255 y así escalarlos en el rango [0, 1]:

CONSTRUCCIÓN DEL MODELO:

Una vez que los datos están preparados, podemos construir nuestro modelo de clasificación de imágenes. Para este ejemplo, utilizaremos una red neuronal convolucional (CNN), la cual constituye una arquitectura comúnmente utilizada para tareas de visión por computadora como la que pretendemos realizar:

En la construcción del modelo, primero definimos un modelo secuencial utilizando ‘tf.keras.models.Sequential([])‘, permitiéndonos agregar capas secuenciales una tras otra. Luego, agregamos capas de convolución 2D seguidas de capas de agrupación máxima para extraer características de las imágenes y reducir la dimensionalidad. Después de varias iteraciones, aplanamos las características en un vector unidimensional y las alimentamos a capas densas para la clasificación final.

Una vez que el modelo está construido, lo compilamos con ‘model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])‘. Aquí, especificamos el optimizador ‘adam‘, una función de pérdida adecuada para problemas de clasificación de múltiples clases, y las métricas que deseamos monitorear durante el entrenamiento, como la precisión. Este proceso de construcción y compilación establece los parámetros esenciales del modelo, preparándolo para el proceso de entrenamiento.

ENTRENAMIENTO DEL MODELO:

Una vez construido y compilado nuestro modelo, podemos entrenarlo utilizando los datos de entrenamiento que definimos con anterioridad:

El código para entrenar el modelo utiliza el método ‘fit()‘, donde proporcionamos los datos de entrenamiento (‘x_train‘) y sus correspondientes etiquetas de clase (‘y_train‘). A su vez, especificaremos el número de épocas (variable ‘epochs‘) de entrenamiento, que determina cuántas veces el modelo verá todo el conjunto de datos de entrenamiento. Además, utilizamos un conjunto de datos de validación (‘x_test‘ y ‘y_test‘) para evaluar el rendimiento del modelo después de cada época. Durante el entrenamiento, el modelo ajusta sus pesos para minimizar la función de pérdida, y al final de cada época, evalúa su desempeño en el conjunto de validación. Este proceso se repite durante el número especificado de épocas, preparando así el modelo para su evaluación final.

Proceso de entrenamiento del modelo.

EVALUACIÓN DEL MODELO:

Finalmente procederemos a la evaluación de nuestro modelo, obteniendo el valor de perdida en el conjunto de datos de prueba (‘test_loss‘) y la precisión (‘test_acc‘). Para ello utilizaremos el método ‘evaluate()‘ del TensorFlow:

CONCLUSIÓN:

En este artículo, hemos explorado cómo utilizar Python junto con TensorFlow para entrenar un modelo de clasificación de imágenes. Desde la preparación de los datos hasta la construcción, entrenamiento y evaluación del modelo, TensorFlow proporciona herramientas poderosas y fáciles de usar para trabajar con imágenes y realizar tareas de aprendizaje automático. Con este conocimiento, estás listo para comenzar a desarrollar tus propios modelos de clasificación de imágenes y explorar el emocionante campo de la visión por computadora.

Saludos.

DETECCIÓN DE TEXTO EN IMAGENES EN PYTHON, CON ‘EasyOCR’.

Destacado

El Reconocimiento óptico de caracteres (‘ROC‘ u ‘OCR‘ por sus siglas en inglés), consiste en la extracción y detección de texto en imágenes. Se trata una tarea común en el campo de la visión por computadora que es ampliamente utilizada en aplicaciones tales como la captura y digitalización de documentos, traducción, detección de fraudes o reconocimiento de información en imágenes medicas. Así, esta semana vamos a aprender a extraer texto de una imagen, utilizando ‘EasyOCR‘ una librería en Python que nos permitirá realizar dicha tarea de una forma rápida y sencilla. Librería que deberemos instalar previamente en nuestro sistema, mediante el comando ‘pip install easyocr‘.

USO BASICO:

Una vez explicado el objetivo de nuestra practica, pasaremos a la extracción de texto de archivos de imagen. En esta ocasión usaremos el entorno de ‘Google Colab‘ en el que empezaremos realizando la instalación de ‘EasyOCR‘:

Tras ello pasaremos a importar la librería en cuestión, para a continuación, crear el objeto ‘reader‘ especificando el idioma (inglés en este caso) del texto que vamos a extraer:

Empezaremos extrayendo texto, en distintos tamaños, de una imagen en blanco y negro:

image.png

Para la lectura del texto en la imagen, usaremos aquí, la función «readtext()» pasando como argumento la ruta al archivo que contiene el texto que queremos obtener:

Esta función nos devolverá tres informaciones de cada línea de texto detectada: Las coordenadas de la imagen en las que se encuentra el área de texto (concebida como caja), el texto detectado y e nivel de confianza entendida como la probabilidad de que el texto detectado por el algoritmo ‘OCR‘ sea correcto. A su vez, podemos usar un bucle para acceder a estas tres informaciones de modo aislado:

Como se ve, el texto detectado en las líneas coincide con el presente en la imagen, lo que resulta coherente con los valores de probabilidad obtenidos.

A su vez, podemos usar «matplotlib» para mostrar el texto detectado en una etiqueta, para cada línea detectada en la imagen:

También podemos utilizar la información almacenada en la variable ‘bbox‘, para dibujar un recuadro que enmarque el área de la imagen ocupada por el texto:

Lo que hemos hecho sobre una imagen en blanco y negro, podremos hacerlo igualmente sobre una imagen a color como esta a la que hemos dado el nombre de «color_image.png«:

color_image.png

CONCLUSIÓN:

EasyOCR es una herramienta poderosa y fácil de usar para detectar texto en imágenes. Su capacidad para manejar múltiples idiomas, su precisión y su facilidad de integración lo hacen útil para una variedad de aplicaciones, desde la automatización de tareas hasta el procesamiento de documentos. En este artículo hemos visto, de un modo básico, como podemos usarle para extraer la información inherente al texto presente un un archivo de imagen y el modo en que podemos usar dicha información para mostrar gráficamente dicho texto en la imagen.

Saludos.

AJUSTE DE BRILLO Y CONTRASTE EN IMAGENES, CON ‘OpenCV’ Y ‘Python’.

Destacado

El ajuste de brillo es una técnica común en el procesamiento de imágenes y visión por computadora. Permite corregir imágenes oscuras, realzar detalles en imágenes sobreexpuestas y ajustar la calidad visual en diversas aplicaciones, como fotografía, detección de objetos y más. En este artículo, exploraremos cómo ajustar el brillo de una imagen utilizando ‘OpenCV‘ y Python. Mostrando varios ejemplos para que puedas comprender y aplicar esta técnica de manera efectiva. Como es habitual, utilizaremos una imagen de muestra para realizar las operaciones:

Como es habitual, antes de empezar deberemos asegurarnos de tener instalados los recursos y librerías necesarios para efectuar las operaciones que queremos realizar. Para esta ocasión, deberemos instalar previamente (si no lo hemos hecho ya) las librerías ‘OpenCV‘ (para manipulación de imágenes) y ‘Numpy‘ (para trabajar con arreglos):

Una vez que tengamos instalado todo lo necesario para trabajar, crearemos un nuevo archivo ‘ajuste_brillo.py‘ en el que empezaremos importando las librerías necesarias para, a continuación, cargar la imagen original (bien introduciendo el nombre de la misma si se encuentra en el mismo directorio del de trabajo, bien introduciendo la ruta hasta la misma en caso contrario):

Una vez cargada la imagen, podremos empezar a ajustar el brillo de la misma. Para ello existen dos funciones en ‘OpenCV‘: ‘cv2.add()‘ con la que podremos incrementar el brillo de la imagen y ‘cv2.subtract()‘ para disminuirlo. Ambas funciones toman dos argumentos: El nombre de la imagen fuente, una matriz que contiene valores de brillo (matriz creada con ‘numpy‘) la cual multiplicaremos por un factor de incremento o decremento de brillo. Empecemos con un ejemplo en el que vamos a incrementar el brillo de la imagen original mediante la función ‘cv2.add()‘ y un factor de incremento de 50, almacenado en la variable ‘brightness_increase‘:

OUTPUT:

Tal y como hemos señalado, podemos disminuir el brillo de nuestra imagen, usando la función ‘cv2.subtract’, multiplicando la matriz de la imagen original por un factor de decremento (variable brightness_decrease‘) de 50. Como en el caso anterior, usaremos la función ‘cv2.imshow()‘ para mostrar tanto la imagen original como su versión modificada:

OUTPUT:

Por otra parte, el ajuste de brillo por sí solo puede no ser suficiente en algunos casos. Para un control más completo, podemos combinar el ajuste del brillo con el del contraste. Para ello podemos usar la función ‘cv2.convertScaleAbs()‘. Esta función toma tres argumentos: la imagen, el factor de escala para el contraste (alpha) y el valor de desplazamiento para el brillo (beta). A continuación mostramos dos ejemplos en los que aumentamos y disminuimos el brillo y contraste de nuestra imagen fuente:

OUTPUT:

OUTPUT:

Como se ve, es muy fácil el efectuar el ajuste de brillo y contraste sobre una imagen usando Python y la librería ‘OpenCV‘. Estos ajustes son útiles en diversas aplicaciones, desde el mejoramiento de imágenes hasta la visión por computadora. A partir de aquí puedes experimentar con los ejemplos proporcionados y personalizar los valores para obtener los resultados deseados en tus imágenes.

Saludos.

AÑADIENDO CONTRASTE A UNA IMAGEN A COLOR, EN PYTHON, CON «OpenCV».

Destacado

Hace algún tiempo, estuvimos viendo el modo en que podíamos (usando el método de ecualización de histogramas) aumentar el contraste de una imagen en escala de grises. En el día de hoy vamos a ver como hacer eso mismo sobre una imagen a color utilizando la librería «OpenCV«. La imagen que vamos a utilizar como muestra es la siguiente:

Tal y como hemos señalado, para realizar la operación propuesta vamos a utilizar la librería «OpenCV«. También necesitaremos la librería «numpy«. Con lo que, antes de empezar, deberemos tener ambas instaladas en nuestro equipo:

Una vez que hayamos realizado la instalación de ambas, procederemos a su importación en nuestro script, y a cargar la imagen en cuestión incluyendo la ruta a la misma en el caso en que se encuentre alojada en un directorio distinto de aquel en el que estemos trabajando:

Una vez hecho esto, tendremos el arreglo de valores de intensidad de nuestra imagen en una variable a la que hemos dado el nombre de «imagen«. A continuación, procederemos a modificar el contraste de la imagen usando un procedimiento que podemos dividir en 5 fases:

1- Se define el valor de gamma como 2.5. Teniendo en cuenta que un valor de gamma mayor que 1 aumentará el contraste, mientras que un valor inferior a dicha cifra disminuirá este.

2- Se crea una tabla de consulta (look-up table) ‘lookUpTable‘, que se utiliza para mapear los valores de píxeles originales a los nuevos valores después de aplicar la transformación de gamma. Esta tabla tiene una fila y 256 columnas, correspondientes a los valores de intensidad de píxeles (0 a 255).

3- Luego, se realiza un bucle ‘for‘ para iterar sobre los valores de intensidad de píxeles (0 a 255).

4- En cada iteración, se aplica la fórmula de la transformación de gamma para calcular el nuevo valor de píxel utilizando la función ‘np.clip()‘, que asegura que el valor esté en el rango [0, 255].

5- Finalmente, la función ‘cv2.LUT()‘ aplica la tabla de consulta ‘lookUpTable‘ a la imagen ‘imagen‘, lo que resulta en una imagen con mayor contraste.

Los 5 pasos planteados quedan plasmados en las siguientes líneas de código:

Por último, podemos mostrar el resultado de la transformación empleando la función ‘imshow()’ de ‘cv2‘:

OUTPUT:

Como puede verse, obtenemos una imagen mucho más nítida que la original, lo cual, se ve especialmente en el color de la montaña (parcialmente oculto por la niebla, en la imagen original) permitiendo la apreciación de una mayor cantidad de detalles en la imagen.

Resumiendo, este código carga una imagen, aumenta su contraste mediante una transformación de gamma con un valor de 2.5 mostrando el resultado de dicha transformación en una ventana. Recuerden que siempre podéis cambiar el valor de ‘gamma’ para obtener diferentes niveles de contraste en la imagen resultante, ajustando el resultado a vuestras necesidades.

Saludos.

TRANSFORMACIÓN RADIAL, AFÍN Y TANGENCIAL EN IMAGENES, CON PYTHON Y «OPENCV».

Destacado

La transformación de imágenes es una técnica fundamental en el campo del procesamiento de imágenes y visión por computadora. Permite modificar la geometría y la apariencia de una imagen mediante la aplicación de diversas operaciones matemáticas. En este artículo, exploraremos tres tipos comunes de transformaciones: la transformación radial, la transformación afín y la transformación tangencial, y cómo implementarlas utilizando el lenguaje de programación Python y la librería «OpenCV» que deberemos tener previamente instalada en nuestro equipo. También vamos a necesitar hacer uso de «Numpy» por lo que igualmente deberemos instalarla, de no haberlo hecho:

Una vez instalada las librerías y recursos que vamos a usar, procederemos a aplicar las transformaciones referidas sobre la siguiente imagen:

«lenna.jpg»

1). TRANSFORMACIÓN RADIAL.

La transformación radial se utiliza para distorsionar una imagen de manera que se parezca a una proyección esférica o cilíndrica. Esta transformación es especialmente útil para corregir distorsiones de lente en fotografías. En Python, podemos utilizar la biblioteca «OpenCV» para realizar esta transformación. A continuación se muestra un ejemplo de código:

OUTPUT:

Tal como se ve en el código, creamos la función «radial_transform()«, la cual, toma como entrada una imagen y un factor de distorsión «k«. En ella, primero, se obtienen las dimensiones de la imagen y se calcula el centro de la misma. Luego, se crea una malla de coordenadas utilizando la función «np.meshgrid()«, para, a continuación, calcular la distancia desde el centro de la imagen a cada punto de la malla. Hecho esto, se calculan las nuevas posiciones de los píxeles de acuerdo a una fórmula que involucra el factor de distorsión y la distancia al centro. Estas nuevas posiciones se utilizan para interpolar los valores de los píxeles de la imagen original y generar una imagen distorsionada utilizando la función «cv2.remap()«. Finalmente, se muestra la imagen distorsionada utilizando «cv2.imshow()«. Al ejecutar el código, se carga una imagen, se aplica la transformación radial con un factor de distorsión específico mostrándose el resultado.

2). TRANSFORMACIÓN AFÍN.

La transformación afín es una transformación lineal que conserva la paralelismo de las líneas. Permite realizar operaciones como rotación, traslación, escalado y cizallamiento en una imagen. A continuación, veremos un ejemplo en el que realizaremos una traslación de 50 pixeles en el eje «x» y 20 en el eje «y«:

OUTPUT:

En este ejemplo, cargamos una imagen y definimos una matriz de transformación afín utilizando la función «np.float32«. Los parámetros «tx» y «ty» representan las cantidades de traslación en el eje x y eje y, respectivamente. Luego, utilizamos la función «cv2.warpAffine» para aplicar la transformación afín a la imagen.

3) TRANSFORMACIÓN TANGENCIAL.

La transformación tangencial permite corregir la distorsión de una imagen causada por lentes o cámaras. Se basa en el modelo de proyección de la cámara y utiliza coeficientes de distorsión para ajustar la imagen (se trata, así, de una transformación que nos permitirá modificar el ángulo de la imagen).

Para aplicar una transformación tangencial, necesitamos conocer los coeficientes de distorsión de la cámara. Estos coeficientes se pueden obtener mediante técnicas de calibración de cámaras (aunque para nuestro caso, nos limitaremos a definirlos nosotros para ver el resultado). Una vez obtenidos estos, podemos utilizar el siguiente código para aplicar la transformación tangencial a una imagen:

OUTPUT:

En este ejemplo, cargamos una imagen y definimos los coeficientes de distorsión «k1«, «k2«, «p1» y «p2«. Luego, creamos una matriz de cámara «matriz_camara» utilizando la función «np.array«, donde especificamos los parámetros intrínsecos de la cámara (que en este caso, nos hemos inventado). A continuación, definimos una matriz de distorsión «matriz_distorsion» con los coeficientes de distorsión. Finalmente, utilizamos la función «cv2.undistort» para aplicar la transformación tangencial a la imagen y mostramos la imagen original y la imagen transformada.

En este artículo, hemos explorado cómo aplicar transformaciones radial, afines y tangenciales a imágenes utilizando Python y la librería «OpenCV«. Estas transformaciones ofrecen la posibilidad de modificar la geometría y corregir distorsiones en las imágenes, lo que resulta útil en una amplia gama de aplicaciones en el campo del procesamiento de imágenes y la visión por computadora. Con las herramientas adecuadas, como «OpenCV«, Python se convierte en una poderosa opción para realizar estas transformaciones y manipular imágenes de manera eficiente y efectiva.

Saludos.

ECUALIZACIÓN DE HISTOGRAMAS EN PYTHON, CON «opencv».

Destacado

Hola y bienvenidos a un nuevo artículo de vuestro blog sobre programación en lenguaje Python, en el que utilizaremos «opencv» para llevar a cabo la ecualización del histograma de una imagen en escala de grises, consistente en la aplicación de un algoritmo que redistribuye los valores de intensidad de esta, logrando una distribución más uniforme. Lo que a su vez dará como resultado, un mayor contrate en la misma.

Pero antes de empezar, deberemos de asegurarnos de tener correctamente instaladas las librerías y recursos que vayamos a utilizar, procediendo a su instalación en caso contrario:

Para nuestro ejemplo, vamos a trabajar con el siguiente archivo de imagen, el cual deberemos cargar usando la función «imread()«. No sin antes hacer las importaciones pertinentes.

No obstante, la ecualización de histogramas es una técnica que solo nos va a servir sobre imágenes con un único canal de color. Por ello, nada más cargar la imagen, deberemos convertirla a escala de grises. Tras ello, usaremos «matplotlib» para mostrarla en pantalla:

OUTPUT:

Dada la naturaleza de la practica que nos ocupa, también será de interés mostrar un histograma en el que se muestre la distribución de los valores de intensidad de la imagen que mostraremos junto a la media de dichos valores (que calcularemos con la función «mean()» de «numpy«) y que representaremos en el histograma, con una línea vertical. Esto lo haremos definiendo una función («show_hist()«) que recibirá como argumentos, el titulo del histograma y el array que contiene los valores de intensidad para calcular el histograma:

De este modo, de nuestra imagen original en escala de grises (cuyos valores hemos almacenado en la variable «gray«) presentará la siguiente distribución:

Lo que nos proponemos a hacer a continuación es realizar una redistribución de los valores de intensidad de la imagen de modo que tengamos una mayor cantidad de pixeles, cuyos valores de intensidad se encuentren distribuidos de un modo más uniforme. Lo que a su vez, repercutirá en la presencia de un mayor contraste en la imagen. Para ello, tenemos una función en «opencv» llamada «equalizeHist()» la cual aplicaremos a nuestra imagen en gris:

OUTPUT:

Se obtiene así una imagen con un mayor contraste en las intensidades de gris. No obstante, también es cierto que si bien, esta función incrementa el contraste de la imagen, también aumenta el nivel de ruido que pueda tener esta además de aparecer como difuminada sobre todo en las regiones más claras. Por su parte, podemos usar nuevamente la función «show_hist()» para mostrar el nuevo histograma:

Es debido a los defectos antedichos por lo que puede interesar la aplicación de otro algoritmo, el «Contrast Limited Adaptive Histogram Equalization» (o «CLAHE«) que lo que hará será realizar la redistribución de valores de forma local, dividiendo la imagen en celdas sobre cuyos pixeles se hará el proceso de ecualización y cuyas dimensiones deberemos definir buscando un mejor resultado, definiendo también, un umbral límite para dicha transformación. Estas variables son las que introduciremos como argumentos de la función «createCLAHE()» la cual se encargará de la aplicación de dicha técnica:

OUTPUT:

Obtenemos nuevamente una imagen de mayor contraste sin perdida de información solo que sin la presencia de ruido y sin el efecto de lavado sobre la misma que apreciábamos en el caso anterior. A su vez, la más uniforme distribución de los valores de intensidad (incrementando el valor de las intensidades más bajas y disminuyendo el de las más altas), puede apreciarse viendo el histograma correspondiente a la nueva imagen:

Como se ve, la ecualización de histogramas es una técnica que nos puede ser de gran utilidad a la hora de dotar de un mayor contrate a imágenes en blanco y negro o escala de grises. Existe una función en «opencv» llamada «normalize()» mediante la cual, y usando la técnica de la normalización, podemos hacer algo muy parecido sobre imágenes a color. Pero de ello hablaremos en otra ocasión.

Podéis encontrar el código completo de este tutorial en el siguiente enlace:

https://github.com/antonioam82/ejercicios-python/blob/master/clahe.py

Saludos.

TRABAJANDO CON CANALES DE COLOR EN PYTHON: MOSTRANDO HISTOGRAMAS.

En el artículo de la pasada semana, estuvimos viendo la forma en la que podíamos mostrar los diferentes canales de color, de una imagen, usando la librería «opencv«. Hoy completaremos aquella explicación, mostrando como podemos hacer uso de histogramas para analizar mejor la distribución de las intensidades de color (tanto en escala de grises, como en cada uno de los canales BGR). Para ello, partiremos del código que usamos para mostrar la imagen de muestra:

OUTPUT:

Lo primero que vamos a hacer es mostrar el histograma relativo a los valores de intensidad de color de nuestra imagen. Para ello, lo primero que haremos será convertir nuestra imagen a escala de grises, para facilitar el cálculo de su histograma. Esto (como vimos en el articulo anterior) lo hacemos con «opencv» y la función «cvtColor()«:

OUTPUT:

CALCULANDO HISTROGRAMAS.

Una vez obtenida nuestra imagen a escala de grises, podemos pasar al cálculo de su histograma, para su posterior representación gráfica. Para ello emplearemos la función «calcHist()«. A su vez, generaremos nuestra representación utilizando la librería «matplotlib«, motivo por el que deberemos importarla previamente:

Como se ve, hemos usado la función «calcHist()» para calcular nuestro histograma, pasando como argumento, en primer lugar, la lista de imágenes (en este caso, solo una) cuya distribución de valores queremos conocer. En segundo lugar, deberemos pasar el número de canales de color que queremos analizar (en este caso, tratándose de una imagen en escala de grises, el valor será 0). En tercer lugar, si queremos utilizar alguna máscara para analizar una determinada porción de la imagen, deberemos especificarla (en este caso lo dejaremos en «None«). Tras ello, especificaremos el número de contenedores (dado que los posibles valores de intensidad varían entre 0 y 255, el valor será de 256). Finalmente, ese mismo rango lo especificaremos como último argumento. Hecho el cálculo, usamos «matplotlib» para mostrar la gráfica siguiente:

Obtenemos así, una gráfica en la que se muestra el número de pixeles (eje «y«) que presentan cada uno de los posibles valores de intensidad (eje «x«). Esto que acabamos de hacer para la imagen en escala de grises, podemos hacerlo igualmente para cada uno de los canales de color en los que esta se puede descomponer, (proceso este que vimos en el anterior artículo y que consistía en la aplicación de la función «split()«):

Como se ve, hemos empezado realizando la descomposición de nuestra imagen en sus tres canales BGR (variables «b«, «g» y «r«) para a continuación, realizar el cálculo de sus correspondientes histogramas (almacenándose en las variables «blue_hist«, «green_hist» y «red_hist«) que a continuación pasaremos como argumentos (junto al título) de una función para mostrar las gráficas, (a la que llamamos «hist()«), obteniendo los siguientes resultados:

OUTPUT:

Blue_Histogram.png
Green_Histogram.png
Red_Histogram.png

Examinando el resultado, podemos ver como es en el canal rojo donde se da las mayores cantidades de pixeles con valores de intensidad más elevados. Lo cual, en este caso, puede intuirse fácilmente examinando las tonalidades predominantes en la imagen original.

Saludos.

TRABAJANDO CON CANALES DE COLOR EN IMÁGENES DIGITALES, CON Python Y ‘opencv’.

Cuando trabajamos con imágenes digitales a color, podemos entender estas como un arreglo en el que el valor de color de cada pixel, viene dado por la combinación de tres valores de intensidad (que variarán de 0 a 255) que se corresponden con los tres canales de color: rojo, verde y azul (que a su vez son los colores básicos de cuyas combinaciones se pueden obtener toda la gama de colores del espectro visible). Pues bien, en este artículo, veremos como podemos obtener por separado dichos canales de color usando la librería «opencv» y que instalaremos con el comando «pip install opencv-python«.

Para nuestro análisis usaremos una imagen a color, la cual leeremos y mostraremos en pantalla, utilizando las funciones ‘imread()‘ y ‘imshow()‘ respectivamente:

OUTPUT:

Una vez cargada nuestra imagen de muestra podemos empezar usando «numpy» y su función «array» para obtener el arreglo de valores de intensidad para cada uno de los canales de color:

OUTPUT:

Obtenemos así representados las intensidades de color, de cada pixel, para los canales azul, verde y rojo (en ese orden). En este caso concreto vemos como los valores de intensidad del canal rojo son, en general, más altos, lo cual concuerda con las tonalidades imperantes en la imagen de muestra.

El orden en el que aquí se muestran los valores de intensidad de cada canal viene del hecho de que «opencv» realiza la lectura de imágenes utilizando el espacio de color «BGR» (en lugar del más común «RGB«). Esto puede plantear problemas, por ejemplo, cuando queremos mostrar una imagen leída por «opencv» utilizando otras librerías, como por ejemplo «matplotlib«:

OUTPUT:

Para estos casos, lo que podremos hacer es convertir previamente nuestra imagen de «BGR» a «RGB» empleando la función «cvtColor()«:

OUTPUT:

A su vez, este cambio también se plasmaría en el orden de los valores de intensidad en el arreglo que obtuvimos con «numpy«:

Siguiendo con nuestros canales de color, «opencv» ofrece una función («split()«) la cual nos permitirá realizar la separación de los tres canales de color, para después mostrarlos en pantalla y por separado:

OUTPUT:

Se muestra así, la distribución por separado, de las intensidades de color (entre 0 y 255) para los canales azul (imagen de la izquierda), verde (imagen central) y rojo (imagen de la derecha) en donde las regiones más claras se corresponden con los valores de intensidad más altos, sucediendo lo contrario con las regiones más oscuras, que representan los valores más bajos.

A su vez, de la misma manera que hay una función que separa los tres canales de color y nos permite representarlos por separado, también hay otra función («merge()«), a la que pasaremos una lista con las variables en las que hemos almacenado los valores de intensidad para cada canal, y que nos permitirá reconstruir la imagen original a partir de los tres canales:

OUTPUT:

Una consideración final que podemos hacer, es con referencia a la salida que obtuvimos cuando mostramos, por separado los tres canales de color. En aquella ocasión de nos mostraron tres imágenes en escala de grises. Lo cual es debido a que estas eran unidimensionales (entendido esto como que sus arreglos estaban compuestos por un único valor de intensidad por pixel).

Para mostrar las intensidades de cada canal, por separado y con su color correspondiente, lo que haremos será incorporar dos valores más por pixel en sus respectivos arreglos. Para ello lo que haremos será usar la función «merge()» para combinar por separado cada canal de color con los valores de una imagen en negro y con las mismas dimensiones, la cual generaremos con la función «zeros()» de «numpy» (dicha imagen en negro tendrá que tener las mismas dimensiones que las imágenes a combinar):

OUTPUT:

En este artículo hemos visto el modo en que podemos mostrar la distribución por separado, de los valores de intensidad para cada canal de color, en una imagen digital, así como el modo en que podemos reconstruir la imagen original a partir de dichos canales. También hemos hecho notar el hecho de que «opencv» lee las imágenes en formato «BGR» y la necesidad de su conversión a formato «RGB» para trabajar con otras librerías como «matplotlib«.

Saludos.

DETECCIÓN Y DIFUMINADO DE ROSTROS EN IMÁGENES EN PYTHON.

Hace ya algún tiempo, estuvimos viendo la manera en la que podemos realizar la detección de rostros humanos en una imagen usando la librería «OpenCv«. Hoy, a aquella practica vamos a añadir la técnica de difuminado de dichos rostros, usando igualmente, la citada librería Esta operación la realizaremos tanto a partir de una foto de prueba, como a partir de la entrada por cámara.

DETECCIÓN Y DIFUMINADO DE ROSTROS EN FOTOGRAFÍAS.

En este primer ejercicio realizaremos la detección y difuminado de un rostro en una imagen de prueba:

Imagen original.

Tal y como hicimos en su momento, empezaremos efectuando la detección del rostro de nuestra imagen usando la librería «OpenCV» y el modelo creado a tal efecto, definido en el archivo «haarcascade_frontalface_default.xml«. Así, comenzaremos cargando nuestra imagen de prueba y creando nuestro detector con dicho modelo:

Una vez cargada la imagen y el modelo que vamos a usar, pasaremos a aplicar este sobre nuestra imagen para a continuación dibujar el área de detección, para finalmente mostrar el resultado mediante el método «imshow()«:

OUTPUT:

Detección de rostro.

Con esto ya tenemos la detección realizada correctamente. Una vez que tenemos delimitada el área, solo nos resta aplicar el efecto de difuminado sobre la misma. Para ello, empezaremos delimitando el área sobre el que vamos a aplicar el efecto (que coincidirá con la del rectángulo dibujado) para finalmente aplicarle el filtro correspondiente. Así reescribiremos el bloque de código anterior para poder aplicar el filtro:

OUTPUT:

Aplicación de difuminado sobre área deseada.

DIFUMINADO DE ROSTRO A PARTIR DE ENTRADA POR CÁMARA.

El procedimiento para la detección de rostros en una entrada por cámara es, en líneas generales, bastante similar (en cuanto a los pasos a dar) al que veíamos en el caso anterior. Solo que en este caso, en lugar de usar «OpenCv» para abrir una imagen, lo vamos a usar para mostrar la entrada recogida por la cámara de nuestro dispositivo, utilizando el método «videoCapture()«. Así, empezaremos iniciando la cámara de nuestro dispositivo y cargando el modelo para detección de rostros del mismo modo que en el ejemplo anterior:

En el bloque siguiente pasaremos a manipular la secuencia de fotogramas que componen la salida de video por cámara al tiempo que en cada uno, procedemos a usar nuestro modelo de detección, para dibujar el área correspondiente:

Por su parte, para aplicar el efecto de difuminado sobre el rostro, simplemente tendremos (tal y como hicimos en el ejemplo anterior) que encontrar el área detectada y usar el método «medianBlur()» para lograr el efecto. Para ello introduciremos los cambios pertinentes en el bloque de código anterior:

OUTPUT:

En los siguientes enlaces tenéis el código completo de ambos ejemplos para que lo probéis vosotros mismos:

PRIMER EJEMPLO:

https://github.com/antonioam82/ejercicios-python/blob/master/blurring_faces_images.py

SEGUNDO EJEMPLO:

https://github.com/antonioam82/ejercicios-python/blob/master/blurring_faces_video.py

A su vez, en el siguiente enlace podéis obtener el modelo usado para la detección de rostros en imágenes:

https://github.com/antonioam82/FaceDetect

Saludos.