OpenCV

Tutorial OpenCV: Carga y visualización de imágenes

OpenCV: Aprende a leer imágenes, gestionar espacios de color y visualizarlas con Matplotlib fácilmente, así como guardarlas con OpenCV en Python.

Aprende OpenCV GRATIS y certifícate

Lectura de imágenes con OpenCV

Para leer imágenes en OpenCV, se utiliza principalmente la función cv2.imread(). Esta función permite cargar una imagen desde una ruta específica y devolverla como un objeto de tipo NumPy ndarray, que representa la matriz de píxeles de la imagen.

El uso básico de cv2.imread() es el siguiente:

import cv2

imagen = cv2.imread('ruta/a/la/imagen.jpg')

En este ejemplo, la variable imagen contendrá la matriz de píxeles de la imagen cargada. Es importante verificar que la imagen se haya cargado correctamente, ya que la función cv2.imread() devolverá None si la ruta es incorrecta o la imagen no puede ser leída. Por tanto, es recomendable incluir una comprobación:

if imagen is None:
    print('Error al cargar la imagen')
else:
    print('Imagen cargada correctamente')

La función cv2.imread() acepta un segundo parámetro opcional llamado flag, que indica el modo en que se leerá la imagen. Los valores más comunes para este parámetro son:

  • cv2.IMREAD_COLOR: Carga la imagen en color. Este es el valor predeterminado.
  • cv2.IMREAD_GRAYSCALE: Carga la imagen en escala de grises.
  • cv2.IMREAD_UNCHANGED: Carga la imagen incluyendo el canal alfa, si está presente.

Por ejemplo, para leer una imagen en escala de grises:

imagen_gris = cv2.imread('ruta/a/la/imagen.jpg', cv2.IMREAD_GRAYSCALE)

Al trabajar con imágenes de distintos formatos y canales, es esencial comprender cómo afectan estos flags al resultado obtenido y al procesamiento posterior de la imagen.

Además, OpenCV es compatible con una amplia variedad de formatos de imagen, como JPEG, PNG, TIFF, BMP y más. Sin embargo, hay que considerar que algunos formatos pueden no soportar ciertas características, como la transparencia en JPEG.

Es común que las imágenes estén en diferentes directorios o que se utilicen rutas relativas y absolutas. Es recomendable utilizar paquetes como os para gestionar las rutas de archivos de manera flexible:

import cv2
import os

ruta = os.path.join('carpeta', 'subcarpeta', 'imagen.png')
imagen = cv2.imread(ruta)

También se puede manejar rutas absolutas utilizando el módulo pathlib:

from pathlib import Path

ruta = Path('/usuarios/usuario/imagenes/imagen.png')
imagen = cv2.imread(str(ruta))

Al cargar imágenes en aplicaciones más complejas, es posible que necesitemos manejar excepciones y errores más detalladamente. OpenCV no lanza excepciones al fallar en la carga de una imagen, por lo que es nuestra responsabilidad verificar la validez del objeto devuelto y actuar en consecuencia.

Visualización con Matplotlib

Después de cargar imágenes con OpenCV, es común querer visualizarlas para verificar resultados o mostrar procesos intermedios. Aunque OpenCV ofrece funciones para mostrar imágenes, como cv2.imshow(), estas funciones pueden presentar limitaciones cuando se trabaja en entornos como Jupyter Notebook. Por ello, es habitual utilizar Matplotlib para visualizar imágenes en estos contextos.

Para visualizar imágenes con Matplotlib, primero debemos importar la biblioteca y utilizar la función plt.imshow(). Sin embargo, es importante tener en cuenta que OpenCV utiliza por defecto el espacio de color BGR, mientras que Matplotlib asume que las imágenes están en formato RGB. Esto significa que si intentamos mostrar una imagen cargada con OpenCV directamente en Matplotlib, los colores aparecerán alterados.

Para corregir este problema, es necesario convertir la imagen de BGR a RGB utilizando la función cv2.cvtColor() de OpenCV. A continuación se muestra un ejemplo completo:

import cv2
import matplotlib.pyplot as plt

# Cargar la imagen con OpenCV
imagen = cv2.imread('ruta/a/la/imagen.jpg')

# Convertir la imagen de BGR a RGB
imagen_rgb = cv2.cvtColor(imagen, cv2.COLOR_BGR2RGB)

# Mostrar la imagen con Matplotlib
plt.imshow(imagen_rgb)
plt.title('Imagen en RGB')
plt.axis('off')  # Ocultar los ejes
plt.show()

En este ejemplo, primero cargamos la imagen utilizando cv2.imread(). Luego, aplicamos la función cv2.cvtColor() para convertirla al espacio de color RGB, almacenando el resultado en la variable imagen_rgb. Finalmente, utilizamos plt.imshow() para mostrar la imagen y plt.show() para renderizarla en pantalla.

Si la imagen original es en escala de grises, es decir, ha sido cargada con el flag cv2.IMREAD_GRAYSCALE, podemos mostrarla directamente sin necesidad de convertir el espacio de color:

# Cargar imagen en escala de grises
imagen_gris = cv2.imread('ruta/a/la/imagen.jpg', cv2.IMREAD_GRAYSCALE)

# Mostrar la imagen en escala de grises
plt.imshow(imagen_gris, cmap='gray')
plt.title('Imagen en Escala de Grises')
plt.axis('off')
plt.show()

Aquí, especificamos el parámetro cmap='gray' en plt.imshow() para indicar que se trata de una imagen en escala de grises. Esto asegura que Matplotlib renderice la imagen correctamente.

Es posible que deseemos mostrar múltiples imágenes en una sola figura para comparar resultados. Matplotlib permite crear subplots para este propósito:

# Crear una figura con dos subplots
fig, axs = plt.subplots(1, 2, figsize=(10, 5))

# Mostrar la imagen original en BGR (sin conversión)
axs[0].imshow(imagen)
axs[0].set_title('Imagen en BGR')
axs[0].axis('off')

# Mostrar la imagen convertida a RGB
axs[1].imshow(imagen_rgb)
axs[1].set_title('Imagen en RGB')
axs[1].axis('off')

# Ajustar el espacio entre subplots y mostrar
plt.tight_layout()
plt.show()

En este caso, al mostrar la imagen original sin convertir, observaremos que los colores no se representan correctamente. Esto ilustra la importancia de la conversión de espacios de color al utilizar OpenCV y Matplotlib juntos.

Otra consideración importante es el manejo de los valores de los píxeles. OpenCV trabaja con matrices de tipo uint8, donde los valores van de 0 a 255. Matplotlib puede manejar estas matrices directamente, pero si realizamos operaciones que cambian los tipos de datos o el rango de valores, debemos asegurarnos de que la imagen esté en un formato adecuado antes de visualizarla.

Por ejemplo, si normalizamos los valores de la imagen al rango [0, 1] convirtiéndola a tipo float, debemos ajustar Matplotlib para que interprete correctamente estos valores:

# Normalizar la imagen al rango [0, 1]
imagen_float = imagen_rgb / 255.0

# Verificar el tipo y los valores
print(f'Tipo de datos: {imagen_float.dtype}, Máximo: {imagen_float.max()}, Mínimo: {imagen_float.min()}')

# Mostrar la imagen normalizada
plt.imshow(imagen_float)
plt.title('Imagen Normalizada')
plt.axis('off')
plt.show()

Es fundamental verificar que los datos estén en el formato esperado para evitar resultados visuales inesperados.

Además, Matplotlib ofrece múltiples opciones para personalizar la visualización, como agregar títulos, modificar escalas de colores, ocultar ejes y superponer gráficos. Esto es útil para crear visualizaciones más informativas y profesionales.

Por último, es posible guardar las figuras generadas con Matplotlib utilizando plt.savefig():

# Guardar la figura actual en un archivo
plt.savefig('imagen_visualizada.png', dpi=300, bbox_inches='tight')

Esto permite almacenar las visualizaciones para su uso en informes, presentaciones o documentos.

Conversión entre espacios de color

En el procesamiento de imágenes, la conversión entre espacios de color es fundamental para aplicar diversas técnicas y realzar características específicas de una imagen. OpenCV proporciona una amplia gama de espacios de color y funciones para convertir imágenes de un espacio a otro utilizando la función cv2.cvtColor().

El espacio de color más común en OpenCV es el BGR (azul, verde, rojo), pero existen otros espacios como RGB, HSV (tono, saturación, valor), HLS (tono, luminosidad, saturación), LAB, entre otros. Cada espacio de color resalta diferentes aspectos de una imagen y es útil para distintas aplicaciones en visión por computador.

Para convertir una imagen de BGR a escala de grises, se utiliza el código de conversión cv2.COLOR_BGR2GRAY:

import cv2

# Cargar imagen en color
imagen_bgr = cv2.imread('ruta/a/la/imagen.jpg')

# Convertir a escala de grises
imagen_gris = cv2.cvtColor(imagen_bgr, cv2.COLOR_BGR2GRAY)

La imagen resultante imagen_gris será una matriz bidimensional, donde cada valor representa la intensidad de gris de un píxel. Esta conversión es esencial para técnicas como el umbralizado y la detección de bordes.

Para cambiar la imagen de BGR a RGB, lo que es especialmente útil al trabajar con bibliotecas que utilizan este orden de canales, se utiliza:

# Convertir de BGR a RGB
imagen_rgb = cv2.cvtColor(imagen_bgr, cv2.COLOR_BGR2RGB)

El espacio de color HSV es muy útil en tareas donde se requiere independencia de la iluminación, como la detección de colores específicos. Para convertir de BGR a HSV:

# Convertir de BGR a HSV
imagen_hsv = cv2.cvtColor(imagen_bgr, cv2.COLOR_BGR2HSV)

En el espacio HSV, el canal Hue (tono) representa el color puro, lo que facilita la segmentación basada en colores. Por ejemplo, para crear una máscara que detecte tonos rojos en la imagen:

# Definir rangos de color en HSV para el rojo
import numpy as np

bajo_rojo = np.array([0, 100, 100])
alto_rojo = np.array([10, 255, 255])

# Crear la máscara
mascara_rojo = cv2.inRange(imagen_hsv, bajo_rojo, alto_rojo)

La función cv2.inRange() genera una imagen binaria donde los píxeles dentro del rango especificado se establecen en blanco (255) y los demás en negro (0). Esta técnica es útil para segmentación de objetos basándose en el color.

Otro espacio de color importante es LAB, que separa la luminosidad (L) de los valores de los colores (A y B), y es útil para mejorar el contraste o realizar correcciones de color:

# Convertir de BGR a LAB
imagen_lab = cv2.cvtColor(imagen_bgr, cv2.COLOR_BGR2LAB)

# Separar el canal de luminosidad
l, a, b = cv2.split(imagen_lab)

# Aplicar ecualización al canal de luminosidad
l_ecualizado = cv2.equalizeHist(l)

# Fusionar los canales nuevamente
imagen_lab_ecualizada = cv2.merge((l_ecualizado, a, b))

# Convertir de LAB a BGR
imagen_bgr_ecualizada = cv2.cvtColor(imagen_lab_ecualizada, cv2.COLOR_LAB2BGR)

En este ejemplo, se mejora el contraste de la imagen utilizando la ecualización del histograma sobre el canal de luminosidad. Luego, se reconvierte la imagen al espacio BGR para visualizarla o procesarla posteriormente.

Es importante conocer los códigos de conversión disponibles en OpenCV, que siguen el patrón COLOR_espacioOrigen2espacioDestino. Algunos códigos comunes incluyen:

  • cv2.COLOR_BGR2GRAY y cv2.COLOR_GRAY2BGR
  • cv2.COLOR_BGR2HSV y cv2.COLOR_HSV2BGR
  • cv2.COLOR_BGR2LAB y cv2.COLOR_LAB2BGR
  • cv2.COLOR_BGR2HLS y cv2.COLOR_HLS2BGR

Para ver todos los códigos de conversión disponibles, se puede utilizar:

import cv2

# Listar todos los códigos de conversión
conv = [attr for attr in dir(cv2) if attr.startswith('COLOR_')]
print(conv)

La capacidad de manipular diferentes espacios de color permite abordar problemas específicos de procesamiento de imágenes. Por ejemplo, para detectar colores similares independientemente de las condiciones de iluminación, el espacio HSV es preferible.

Además, se pueden realizar conversiones en cascada para pasar de un espacio de color a otro que no tenga una conversión directa. Sin embargo, es recomendable hacerlo en pasos mínimos para evitar pérdidas de información.

A la hora de trabajar con videos o secuencias de imágenes, es habitual convertir cada fotograma al espacio de color adecuado antes de aplicar el procesamiento. Esto se debe a que ciertos algoritmos operan más eficientemente o producen mejores resultados en espacios de color específicos.

Un aspecto clave al realizar conversiones es tener en cuenta el rango de valores de cada canal en el espacio de color destino. Por ejemplo, en el espacio HSV en OpenCV, el canal Hue tiene valores entre 0 y 179, no entre 0 y 360 como en otras representaciones. Los canales Saturation y Value van de 0 a 255.

Al combinar conversiones de espacio de color con otras operaciones, como la detección de bordes o el suavizado, es posible crear pipelines de procesamiento más robustos y adaptados a las características de las imágenes a analizar.

Manipulación de imágenes como arrays NumPy

Las imágenes en OpenCV se manejan internamente como arrays NumPy, lo que permite utilizar operaciones y funciones de esta potente biblioteca para procesar y manipular imágenes de forma eficiente. Al comprender que una imagen es esencialmente una matriz multidimensional, podemos aplicar técnicas de procesamiento de datos numéricos directamente sobre las imágenes.

Cuando se carga una imagen con cv2.imread(), se obtiene un objeto de tipo numpy.ndarray. Por ejemplo:

import cv2

imagen = cv2.imread('ruta/a/la/imagen.jpg')
print(type(imagen))  # <class 'numpy.ndarray'>

Este array tendrá una forma (shape) que depende del tipo de imagen:

  • Para imágenes en color: (alto, ancho, canales)
  • Para imágenes en escala de grises: (alto, ancho)

Es fundamental conocer la dimensión y estructura del array para manipularlo correctamente.

Por ejemplo, para comprobar las dimensiones y el tipo de datos de la imagen:

print(f'Dimensiones: {imagen.shape}')
print(f'Tipo de datos: {imagen.dtype}')

Acceso y modificación de píxeles

Podemos acceder a los valores de los píxeles directamente utilizando indexación de arrays. Por ejemplo, para acceder al píxel en la posición (fila, columna):

# Acceder al píxel en la posición (100, 200)
pixel = imagen[100, 200]
print(f'Valor del píxel: {pixel}')

En el caso de una imagen en color, pixel será un array con los valores de los canales BGR:

# Valores de los canales B, G y R
azul = pixel[0]
verde = pixel[1]
rojo = pixel[2]

Para modificar el valor de un píxel y establecerlo en blanco:

imagen[100, 200] = [255, 255, 255]

Esta capacidad permite alterar directamente los píxeles de la imagen para operaciones como enmascaramiento, dibujo o reparación de imágenes.

Slicing y regiones de interés (ROI)

El slicing o corte de arrays NumPy facilita la selección y manipulación de regiones específicas de la imagen, conocidas como Regiones de Interés (ROI). Por ejemplo, para extraer una sección de la imagen:

# Definir los límites de la ROI
x_inicio, x_fin = 50, 150
y_inicio, y_fin = 100, 200

# Extraer la ROI
roi = imagen[y_inicio:y_fin, x_inicio:x_fin]

Ahora, roi es un subarray que representa la porción seleccionada de la imagen original.

Para modificar una región completa, por ejemplo, rellenarla con un color sólido:

# Rellenar la ROI con color verde
imagen[y_inicio:y_fin, x_inicio:x_fin] = [0, 255, 0]

Este tipo de manipulación es útil en aplicaciones de segmentación o para destacar áreas específicas de una imagen.

Operaciones de canal

Las imágenes en color tienen múltiples canales (B, G, R). Podemos separar y manipular estos canales individualmente:

# Separar los canales
b, g, r = cv2.split(imagen)

# Trabajar con el canal azul
b_modificado = b * 0.5  # Reducir la intensidad al 50%

# Fusionar los canales nuevamente
imagen_modificada = cv2.merge((b_modificado, g, r))

La función cv2.split() separa la imagen en sus canales individuales, y cv2.merge() los combina nuevamente. Esto permite realizar operaciones específicas en un solo canal, como ajustar el brillo o aplicar filtros.

Operaciones aritméticas

Gracias a NumPy, es posible realizar operaciones aritméticas y matemáticas sobre las imágenes de forma vectorizada y eficiente. Por ejemplo, para aumentar el brillo de una imagen:

import numpy as np

# Convertir a tipo float para evitar desbordamiento
imagen_float = imagen.astype(np.float32)

# Incrementar el brillo en 50 unidades
imagen_brillo = imagen_float + 50

# Limitar los valores al rango [0, 255] y convertir de nuevo a uint8
imagen_brillo = np.clip(imagen_brillo, 0, 255).astype(np.uint8)

En este caso, utilizamos np.clip() para asegurar que los valores se mantengan dentro del rango válido para una imagen de tipo uint8.

Para multiplicar la imagen y ajustar el contraste:

# Aumentar el contraste multiplicando por 1.2
imagen_contraste = imagen_float * 1.2
imagen_contraste = np.clip(imagen_contraste, 0, 255).astype(np.uint8)

Estas operaciones permiten transformaciones globales sobre la imagen, afectando a todos los píxeles simultáneamente.

Aplicación de funciones matemáticas

Podemos aplicar funciones matemáticas de NumPy sobre las imágenes. Por ejemplo, calcular la raíz cuadrada de los valores de los píxeles:

imagen_sqrt = np.sqrt(imagen_float)
imagen_sqrt = np.clip(imagen_sqrt, 0, 255).astype(np.uint8)

O aplicar una transformación gamma:

gamma = 2.2
imagen_gamma = np.power(imagen_float / 255.0, gamma) * 255
imagen_gamma = np.clip(imagen_gamma, 0, 255).astype(np.uint8)

La corrección gamma es útil para ajustar la luminancia de las imágenes y mejorar la percepción visual.

Uso de máscaras

Las máscaras son arrays binarios que permiten seleccionar píxeles específicos en base a una condición. Por ejemplo, crear una máscara para seleccionar píxeles con intensidad alta en el canal rojo:

# Crear una máscara para el canal rojo
mascara_rojo = imagen[:, :, 2] > 200  # Canal R mayor que 200

# Aplicar la máscara sobre la imagen
imagen_rojo_alto = imagen.copy()
imagen_rojo_alto[~mascara_rojo] = 0  # Establecer a negro donde la máscara es False

Ahora, imagen_rojo_alto muestra solo las áreas donde el canal rojo tiene valores altos. Las máscaras permiten realizar segmentaciones y filtrados basados en condiciones lógicas.

Transposición y rotaciones

La manipulación de arrays también permite realizar operaciones como la transposición o la rotación de imágenes:

# Transponer la imagen (intercambiar filas y columnas)
imagen_transpuesta = np.transpose(imagen, (1, 0, 2))

# Rotar la imagen 90 grados en sentido antihorario
imagen_rotada = np.rot90(imagen)

Estas operaciones pueden ser útiles en preprocesamiento o para preparar las imágenes antes de pasarlas a algoritmos específicos.

Cambio de tipo de datos

Es posible cambiar el tipo de datos de la imagen para operaciones que lo requieran, como trabajar con flotantes en el rango [0, 1]:

# Convertir la imagen al rango [0, 1] de tipo float32
imagen_normalizada = imagen.astype(np.float32) / 255.0

Este formato es común en algoritmos que requieren precisión decimal o en técnicas de aprendizaje automático.

Combinación de imágenes

Podemos combinar varias imágenes utilizando operaciones de NumPy. Por ejemplo, para crear una imagen que es la suma ponderada de dos imágenes:

# Cargar dos imágenes del mismo tamaño
imagen1 = cv2.imread('imagen1.jpg')
imagen2 = cv2.imread('imagen2.jpg')

# Calcular la suma ponderada
alpha = 0.7
beta = 0.3
imagen_combinar = cv2.addWeighted(imagen1, alpha, imagen2, beta, 0)

La función cv2.addWeighted() realiza una suma ponderada, útil para efectos de transparencia o fusiones.

Inversión de colores

Como ejemplo, para invertir los colores de una imagen, podemos utilizar la operación de complemento:

# Invertir los colores de la imagen
imagen_invertida = 255 - imagen

Este sencillo cálculo invierte los valores de los píxeles, creando un efecto de negativo fotográfico.

Ventajas de utilizar NumPy

El uso de NumPy para manipular imágenes ofrece varias ventajas:

  • Eficiencia: Las operaciones vectorizadas son más rápidas que los bucles explícitos en Python.
  • Flexibilidad: Permite aplicar una amplia gama de operaciones matemáticas.
  • Integración: Facilita la interoperabilidad con otras bibliotecas que utilizan arrays NumPy.

Es importante evitar el uso de bucles for anidados para procesar píxeles individualmente, ya que esto resulta en un rendimiento inferior. Siempre que sea posible, se deben utilizar las operaciones vectorizadas que proporciona NumPy.

Al manipular imágenes como arrays NumPy, es importante ser consciente del rango de valores y del tipo de datos para evitar errores como desbordamientos o pérdidas de precisión. Además, siempre debemos asegurarnos de que las operaciones realizadas sean compatibles con el formato de la imagen y los requisitos de los algoritmos posteriores.

La comprensión profunda de cómo las imágenes se representan y manipulan a nivel de array abre un vasto campo de posibilidades para el procesamiento avanzado y creativo de imágenes en OpenCV.

Guardado de imágenes procesadas

Una vez que hemos procesado imágenes utilizando OpenCV, es fundamental saber cómo guardar las imágenes resultantes para su uso posterior o para compartir los resultados. La función principal para este propósito es cv2.imwrite(), que permite escribir una imagen en un archivo con el formato que especifiquemos.

El uso básico de cv2.imwrite() es sencillo y requiere dos parámetros: el nombre del archivo (incluyendo la extensión) y la imagen que deseamos guardar. Por ejemplo:

import cv2

# Supongamos que 'imagen_procesada' es la imagen que hemos modificado
cv2.imwrite('imagen_procesada.jpg', imagen_procesada)

En este ejemplo, la imagen procesada se guarda en el archivo 'imagen_procesada.jpg' en el directorio actual. El formato en que se guardará la imagen se determina por la extensión del archivo proporcionado.

Es importante verificar que la imagen se ha guardado correctamente. La función cv2.imwrite() devuelve un valor booleano que indica el éxito de la operación:

resultado = cv2.imwrite('imagen_procesada.jpg', imagen_procesada)
if resultado:
    print('Imagen guardada exitosamente')
else:
    print('Error al guardar la imagen')

Al trabajar con diferentes formatos de imagen, podemos ajustar parámetros específicos de cada formato al guardar la imagen. Por ejemplo, al guardar en formato JPEG, es posible especificar la calidad de la compresión:

# Guardar con una calidad del 90% en formato JPEG
cv2.imwrite('imagen_calidad90.jpg', imagen_procesada, [cv2.IMWRITE_JPEG_QUALITY, 90])

En este caso, cv2.IMWRITE_JPEG_QUALITY es el parámetro que indica la calidad de la imagen, y el valor 90 establece una calidad alta. Los valores permitidos van desde 0 hasta 100, donde 100 representa la máxima calidad y menor compresión.

De manera similar, al guardar imágenes en formato PNG, podemos ajustar el nivel de compresión:

# Guardar en formato PNG con nivel de compresión 5 (rango 0-9)
cv2.imwrite('imagen_compresion5.png', imagen_procesada, [cv2.IMWRITE_PNG_COMPRESSION, 5])

En el caso de PNG, cv2.IMWRITE_PNG_COMPRESSION controla el grado de compresión, donde 0 es sin compresión y 9 es la máxima compresión.

Si estamos trabajando con imágenes que incluyen un canal alfa para transparencia, como imágenes en formato PNG, es esencial conservar este canal al guardar la imagen:

# 'imagen_con_transparencia' es una imagen RGBA
cv2.imwrite('imagen_transparente.png', imagen_con_transparencia)

Es fundamental asegurarse de que los datos de la imagen están en el formato y tipo de datos correctos antes de guardarla. OpenCV espera que las imágenes sean arrays de tipo uint8 con valores en el rango [0, 255]. Si hemos realizado operaciones que modifican el tipo de datos o el rango de valores, debemos normalizar y convertir la imagen adecuadamente:

import numpy as np

# Supongamos que 'imagen_float' es una imagen con valores en punto flotante en el rango [0.0, 1.0]
imagen_uint8 = (imagen_float * 255).astype(np.uint8)
cv2.imwrite('imagen_normalizada.png', imagen_uint8)

Al guardar imágenes en otros espacios de color, debemos tener precaución. Si hemos procesado la imagen en un espacio de color distinto al BGR estándar de OpenCV, como HSV o LAB, es necesario convertirla de nuevo a BGR antes de guardarla para asegurarnos de que se visualizará correctamente:

# Convertir de HSV a BGR antes de guardar
imagen_bgr = cv2.cvtColor(imagen_hsv, cv2.COLOR_HSV2BGR)
cv2.imwrite('imagen_convertida.jpg', imagen_bgr)

Si necesitamos guardar imágenes en escala de grises, podemos hacerlo directamente. OpenCV detectará que la imagen tiene un solo canal y la guardará apropiadamente:

# 'imagen_gris' es una imagen en escala de grises
cv2.imwrite('imagen_gris.png', imagen_gris)

En ocasiones, es necesario guardar imágenes con metadatos o propiedades específicas. OpenCV permite agregar ciertos parámetros al guardar imágenes en formatos que los soportan. Por ejemplo, al guardar en formato TIFF, podemos especificar si queremos almacenar la imagen con compresión:

# Guardar en formato TIFF con compresión LZW
cv2.imwrite('imagen_compresion_lzw.tiff', imagen_procesada, [cv2.IMWRITE_TIFF_COMPRESSION, 5])

Es útil conocer los diferentes parámetros de codificación que OpenCV ofrece para cada formato. Algunos de los parámetros más comunes son:

  • cv2.IMWRITE_JPEG_QUALITY: Calidad de JPEG (0-100).
  • cv2.IMWRITE_PNG_COMPRESSION: Nivel de compresión para PNG (0-9).
  • cv2.IMWRITE_TIFF_COMPRESSION: Tipo de compresión para TIFF.
  • cv2.IMWRITE_JPEG_PROGRESSIVE: Configurar JPEG como progresivo (0 o 1).

Por ejemplo, para guardar un JPEG como progresivo, lo cual es útil para imágenes web que deben cargarse gradualmente:

# Guardar JPEG progresivo
cv2.imwrite('imagen_progresiva.jpg', imagen_procesada, [cv2.IMWRITE_JPEG_PROGRESSIVE, 1])

En entornos que requieren alta eficiencia, como aplicaciones en tiempo real, es posible que deseemos ajustar estos parámetros para optimizar la velocidad de guardado y el tamaño de los archivos resultantes.

Al guardar imágenes, también debemos considerar la profundidad de bits. OpenCV soporta imágenes de mayor profundidad, como imágenes de 16 bits por canal. Si estamos trabajando con tales imágenes, debemos asegurarnos de que el formato de archivo y el visor de imágenes soporten esta profundidad:

# Supongamos que 'imagen_16bits' es una imagen con tipo de datos uint16
cv2.imwrite('imagen_16bits.png', imagen_16bits)

Sin embargo, hay que tener en cuenta que no todos los formatos de imagen o visores son compatibles con imágenes de alta profundidad, y pueden realizar una conversión implícita a 8 bits.

Aprende OpenCV GRATIS online

Todas las lecciones de OpenCV

Accede a todas las lecciones de OpenCV y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Accede GRATIS a OpenCV y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Entender el uso de cv2.imread() y sus flags para cargar imágenes en diferentes modos.
  • Aprender a manejar errores de lectura de imágenes.
  • Practicar la visualización de imágenes con Matplotlib.
  • Dominio de la conversión de espacios de color (BGR a RGB) al visualizar con Matplotlib.
  • Uso de librerías os y pathlib para gestión de rutas de archivos.