Mostrando entradas con la etiqueta Pillow. Mostrar todas las entradas
Mostrando entradas con la etiqueta Pillow. Mostrar todas las entradas

jueves, 16 de abril de 2026

DATOS. Limpieza de datos

Datos semi-estructurados PDF (I)

Tabla-Imagen

Con frecuencia una de las fuentes de datos estructurados son los documentos de texto, concretamente los documentos PDF. Realmente se trata de una fuente doblemente compleja: son realmente datos estructurados a nuestros ojos, pero precisan un tratamiento manual de tabulación (por ejemplo), pero están muy lejos de serlo para un ordenador, especialmente las "tablas" .pdf.

Antes de seguir y para que no queden dudas respecto al objetivo que se persigue aquí, diré que entiendo por manipulación o tratamiento de datos tabulados en documentos de texto el procedimiento cuyo objetivo último es la creación de estructuras asimilables a una tabla o base de datos que puede ser tratadamediante procedimientos de acceso y consulta a datos estructurados. Digo "objetivo último" porque realmente no siempre se puede garantizar su logro, al menos no de forma directa.

Para un tratamiento ofimático "clásico" no existe diferencia entre un documento .pdf y un documento .docx (o un documento .odt), aunque es posible manipular directamente estos últimos mediante procedimientos relativamente simples basados en los mismos servicios ofimáticos y/o en la combinación procesador-hoja de cálculo. Esta posibilidad se complica si las tablas están en un documento .pdf, pero puede ser una complicación salvable, especialmente si los datos no están sujetos a confidencialidad; si sí lo están va a depender de la suerte que tengamos en el procedo de captura de los datos: si es posible copia-pega, no vamos a tener más trabajo que si se tratara de tablas .docx (o casi), pero si no se dejan capturar de este modo no nos va a quedar más remedio que copiarlos manualmente o casi manualmente.

Pero la automatización se complica significativamente cuando la fuente radica en un documento .pdf, especialmente si estas tablas contienen información confidencial, que no es posible derivar a recursos especialidados, e incluso posiblemente las dificultades persistan en caso de optar por estos medios. De todas formas, en lo que a un SEO se refiere, ni por presupuesto ni por razones de confidencialidad podemos recurrir a ellos medios y la consecuencia es que o bien renunciamos a automatizar el acceso a estas tablas (lo más frecuente) o bien aplicamos procedimientos de automatización que sólo resuelven el problema de forma parcial y sin garantia de estar libres de error.

Deberemos, pues, estar dispuestos a realizar algún tipo de intervención ofimática complementaria como las que se explican en esta entrada. Gran parte de las dificultades se deben a la complejidad que para la digitalización tiene las tablas-pdf, las cuales que presentan diferentes comportamientos no siempre fáciles de predecir ni necesariamente invariables en el mismo documento. Es por ello que las tecnologías de automatización pueden fracasar total o parcialmente, sin que sea garantía de éxito ni la complejidad del recurso de automatización ni que sea actual.

Sobre estas cuestiones trabajaremos en posteriores entradas, pero en esta quiero presentar la opción que se viene a considerar como "el último recurso" y que resuelve parcialmente la automatización del acceso al contenido de las tablas. Me refiero a la conversión de éstas en una imagen y el posterior tratamiento de la imágen mediante técnicas OCR.

Aunque lo más ajustado a un procedimiento de automatización sería convertir automáticamente el .pdf en imagen, el coste de este procedimiento es suficientemente elevado en términos de recursos hardware y computacionales y de memoria como para que no me plantee esta opción como punto de partida, máxime cuando disponemos de un procedimiento tan sencillo como barato: crear manualmente la imagen mediante Imprimir pantalla, procedimiento este perfectamente funcional si la tarea afecta a un pequeño número de documentos. Otra cosa sería si el número de documentos fuera muy elevado y se requiera usar la fotocopiadora como scanner y replantear el trabajo como resposabilidad de equipo. En la imagen que sigue te muestro el resultado (anonimizado) de convertir en imagen la segunda tabla. De paso nos servirá para comprobar qué resulta al aplicar el procedimiento ocr

He de decir que, según IA-Gemnini existen opciones para automatizar esa captura de pantalla, pero no vamos a plantearlas ahora, optando por el procedimiento simple que presuponer un trabajo liviano sobre unos pocos documentos. De este modo nos podremos centrar en automatizar de la conversión de la tabla-imagen a texto mediante el siguiente script:


'''
Acceso a tablas convertidas en img manualmente mediante Imprimir pantalla
El script de Python usa pytesseract como OCR lo que implica tener instalado Tesseract
en el sistema.

Script desarrollado haciendo uso de IA-Gemini para mejoras de funcionamiento
implementadas a demanda específicada por el autor.

****************************************************************************************
--- FASES DEL PROCESO -------------------------
****************************************************************************************
'''

#0. Carga de bibliotecas ---------------------

import pytesseract
from PIL import Image
import os

# 1. Configuraciones y acceso a imagen -------------------------

# Configuración de Tesseract
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'

# Configuración de las rutas de salida
nombre_carpeta = 'tablas'
nombre_archivo_txt = 'resultado_ocr.txt'

# Obtener la ruta del directorio donde se ejecuta el script
directorio_actual = os.path.dirname(os.path.abspath(__file__))
ruta_tablas = os.path.join(directorio_actual, nombre_carpeta)

# Crear la carpeta 'tablas' si no existe
if not os.path.exists(ruta_tablas):
    os.makedirs(ruta_tablas)

# Entrada nombre o ruta de img
nombre_imagen = input("Introduce el nombre del archivo de la imagen o su ruta completa (sin comillas): ").strip()

# 2. Procesamiento de OCR -----------------------------------

# Verificamos si el archivo existe antes de continuar
if not os.path.isfile(nombre_imagen):
    print(f"Error: El archivo '{nombre_imagen}' no se encuentra en la ruta especificada.")
else:
    try:
# Iniciamos el procesamiento OCR
        img = Image.open(nombre_imagen)
        texto = pytesseract.image_to_string(img, lang='spa')

# 4. Mostrar y guardar resultado -----------------------------

# Mostrar resultado en consola
        print("\nTexto extraído con éxito:")
        print("-" * 30)
        print(texto)
        print("-" * 30)

# Guardar resultado en archivo TXT usando el nombre de la imagen original para evitar sobreescritura
        nombre_base = os.path.splitext(os.path.basename(nombre_imagen))[0]
        ruta_final_txt = os.path.join(ruta_tablas, f"{nombre_base}.txt")
        
        with open(ruta_final_txt, 'w', encoding='utf-8') as f:
            f.write(texto)
        
        print(f"Archivo guardado en: {ruta_final_txt}")

    except Exception as e:
        print(f"Ocurrió un error al procesar la imagen: {e}")

Los comentarios que acompañan al script, redactados ex-profeso, hacen innecesario su comentario, pero no lo que resulta de su aplicación.

La ventaja que tiene este (que hemos llamado) "último recurso": la conversión de la tabla-pdf en imagen, es que, si la calidad de ésta es buena (y lo debe ser al proceder directamente del texto), el OCR funciona correctamente y transforma el contenido en texto accesible desde Bloc de notas y similares, sin errores ni omisiones. La imagen que sigue muestra la captura de pantalla de ese texto en lo que respecta a la misma tabla 2 que antes mostramos en pdf-img.

Puedes observar que realmente toda la información está ahí: las etiquetas de los campos, los datos, los que sí están (y que aquí ocultamos) y los que no. Ahora bien, esta imagen también muestrar de forma clara, que el resultado se asemeja más a lo que se ve, a la apariencia de lo que se ve que a los datos que muestra: realmente lo obtenido no es una estructura etiqueta-dato, son tres líneas que contienen ciertos textos, sin diferenciar qué papel juega cada uno de ellos, ni reconocer que falta una cuarta línea. Es evidente que estamos aun lejos de haber obtenido una tabla de datos o estructura que se le parezca; llegar a ello va a requerir un tratamiento específico a posteriori.

Esto hace más necesario aun guardar lo obtenido en, por ejemplo, un archivo de texto como .txt que nos permita darle ese tratamiento, al menos de momento mediante recursos ofimáticos, ya que es la forma más básica, cierto, pero también la solución más eficiente, rápida y segura disponible por ahora. Aquí, reitero, explico cómo.

martes, 21 de octubre de 2025

MAV. Python.

Pillow

Matriz a partir de imagen


En la [entrada anterior] creamos una imagen a partir de los datos de una matriz. Ahora haremos el proceso inverso: obtener los datos numéricos que definen una imagen dada, lo que equivale a generar una matriz a partir de esos datos.

 

Lo interesante de lo que estamos haciendo es que podemos trabajar con datos numéricos para crear imágenes y viceversa: obtener los datos numéricos de los que se compone una imagen digitalizada. A partir de esto podemos realizar manipulaciones generales o específicas del color y, a partir de éste, también del dibujo y de las formas que conforman la imagen.

En el script que sigue obtenemos la matriz de datos de una imagen dada y, partiendo de ésta, volvemos a construir la imagen, en este caso, sin modificación alguna respecto a la original.

from PIL import Image
import numpy as np

#Cargar imagen

img_dir = 'img/Paisaje.jpg'
img = Image.open(img_dir)

#Visualizamos la imagen cargada

img.show()

#Convertimos la imagen en matriz

array_img = np.array(img)

#Visualizamos la matriz

print(array_img)

#Convertimos de nuevo la matriz en imagen

img_array = Image.fromarray(array_img)

#Visualizamos la imagen creada

img_array.show()

Para ello ha sido suficiente con importar ambas bibliotecas (Pillow y NumPy) y usar dos funciones específicas, una asociada a Numpy (array_img = np.array(img)) y otra a Pillow (img_array = Image.fromarray(array_img)). La primera para convertir la imagen en una matriz y la segunda para invertir el procedimiento.

A partir de aquí se nos abren todas las opciones que derivan del trabajo con matrices numéricas. Todo un mundo.


sábado, 18 de octubre de 2025

MAV. Python.

Pillow

Filtros


Avanzando en el manejo de imágenes trataré en esta entrada sobre una forma compleja de modificarlas. Me refiero al uso de filtros. Trataremos algunos de ellos mediante el módulo ImageFilter.



Un filtro de imágenes es el procesamiento de la imagen para su mejora o modificación, a fin de resultar cierto contenido o mejorar los valores de la imagen desde diferentes perspectivas (luminosidad, modificación del color, nitidez...).

El uso de filtros nos interesa, pues, por los efectos técnicos y artísticos de los mismos, pero también (y es lo que aquí nos trae) por motivos relativos al propio procesamiento, digamos que como preparación previa para posteriores desarrollos, como el reconocimiento automatizado de cierto contenido en las imágenes.

No obstante, en estos momentos nos limitaremos a explicar un número determinado (y limitado) de filtros y mostrar sus efectos. Se trata, pues, de completar la colección de herramientas que hemos ido viendo en entradas precedentes. Además nos sirve de enlace con la temática que desarrollaremos posteriormente, la cual, aunque no hablemos de ella ahora, es la que posibilita los procedimientos que trataremos.

El primer paso para aplicar filtros es importar los módulos...

from PIL import Image, ImageFilter

... y cargar la imagen (vg)...

#Directorio de la imagen
img_dir = 'img/cuadro.png'

#Imagen original
img = Image.open(img_dir)

... la cual, por motivos didácticos, nos interesa ahora que sea compleja y de calidad. En todo caso, el efecto de algunos filtros es fácilmente detectable, pero el de otros no lo es o depende de las características de la imagen original; por eso te recomiendo que pruebes con diferentes imágenes.

Por otra parte, la sintaxis es muy simple:  función filter() aplicada a la variable asociada al archivo (vg. img.filter()) que contiene como parámetro la clase ImageFilter seguida del atributo NOMBRE_DEL_FILTRO, todo ello asociado a una nueva variable (img_FiltroX = img.filter(ImageFilter.CONTOUR)).

Te dejo a continuación el script con los filtros de mayor interés del módulo ImageFilter, aunque sobre eso hay opiniones. El código de cada filtro está comentado (por eso lo dejo en tinta negra) para que puedas activarlos (y visualizarlos) de forma sucesiva.

from PIL import Image, ImageFilter

#Directorio de la imagen
img_dir = 'img/formas.png'

#Imagen original
img = Image.open(img_dir)

img.show() #Ver imagen

#Modificaciones mediante filtros  -----------------------------------------------

#Filtro BLUR (difuminar)
'''
img_Blur = img.filter(ImageFilter.BLUR)
img_Blur.show()
'''
#Filtro CONTOUR (contorno)
'''
img_Cont = img.filter(ImageFilter.CONTOUR)
img_Cont.show()
'''
# Filtro DETAIL (detalle)
'''
img_Det = img.filter(ImageFilter.DETAIL)
img_Det.show()
'''
#Filtros EDGE_ENHANCE y EDGE_ENHANCE_MORE  (realzar bordes)
'''
img_Bor1 = img.filter(ImageFilter.EDGE_ENHANCE)
img_Bor1.show()
'''
'''
img_Bor2 = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
img_Bor2.show()
'''
#Filtro EMBOSS (efecto grabado)
'''
img_Emb = img.filter(ImageFilter.EMBOSS)
img_Emb.show()
'''
#Filtro FIND_EDGES (detección de bordes)
'''
img_BorDetec = img.filter(ImageFilter.FIND_EDGES)
img_BorDetec.show()
'''
#Filtro SHARPEN (agudizar)
'''
img_Ag = img.filter(ImageFilter.SHARPEN)
img_Ag.show()
'''
#Filtros SMOOTH y SMOOTH_MORE (suavizar)
'''
img_Su1 = img.filter(ImageFilter.SMOOTH)
img_Su1.show()
'''
'''
img_Su2 = img.filter(ImageFilter.SMOOTH_MORE)
img_Su2.show()
'''

El esperado efecto de cada filtro queda explicado en el comentario que antecede, así que no es necesaria más explicación. Lo que sí te sugiero desde el punto de vista técnico-estético, que es el que ahora nos interesa, es que pruebes con diferentes imágenes (tamaño, calidad, formato, complejidad compositiva...) 

viernes, 17 de octubre de 2025

MAV. Python

Pillow

Usos básicos (IV)



Esta entrada complementa [la anterior], incluso puede que debiera ser previa pero en todo caso considero que no debe faltar en esta exposición de recursos para el tratamiento de imágenes ya que en ella trato sobre una función básica en Pillow relativa al cambio de tipo de imagen.

 

Me estoy refiriendo al cambio de modelo de imagen según sus atributos de color, tema este de cierta complejidad, pero que aquí vamos a resumir de forma drástica a las cuestiones que considero tienen mayor interés, quedando el resto para que tú profundices en ellas.

Por mi parte me limitaré a decir que podemos trabajar con imágenes en blanco y negro, imágenes en escala de grises (esta conversión ya la vimos en la entrada antes referida) e imágenes en color. Y dentro de estas últimas podemos distinguir entre imágenes formadas por combinaciones de colores básicos (formato RBG, extensión jpg) e imágenes que añaden a lo anterior información sobre niveles de transparencia (formato RGBA, extensión png). No son los únicos, pero por ahora es suficiente.

Empecemos por lo de siempre...

from PIL import Image

... es suficiente para lo que tenemos que hacer, no siendo necesarios (al contrario que antes) más módulos. Cargamos una imagen en formato png (por eso de trabajar con el formato más complejo)...

#Directorio de la imagen
img_dir = 'img/Estadistica.png'

#Imagen original
img = Image.open(img_dir)

... y visualizamos su atributo modo...

print(img.mode) -> Devuelve RGBA

Y para finalizar este proceso (ya conocido) podemos visualizar la imagen

img.show()

A partir de aquí empezaremos con las transformaciones que partirán siempre de la imagen original para facilitar la comparación.

Primero convertimos la imagen a escala de grises. Esto ya lo sabemos hacer con el módulo ImageOps y la función grayscale() (img_gris = ImageOps.grayscale(img)), pero ahora lo haremos desde el módulo principal Image mediante la función convert() (la verdadera artífice de esta conversión, que requiere como parámetro el identificador del modo color, concretamente L para la conversión a escala de grises (img_gris = img.convert('L'))

El paquete completo de instrucciones incluye la identificación del modo, el visionado de la nueva imagen (que podremos comparar con la original) y su archivo como imagen.

#Escala de grises
img_gris = img.convert('L')
print(img_gris.mode)             -> Devuelve L
img_gris.show()
img_gris.save('img/grafgris.png') #Guardar imagen

Si tratamos de invertir el proceso (convertir L a color, lógicamente obtenemos de nuevo una imagen en escala de grises, pero su modo sí se modifica al especificado en la conversión:

  • convert('RGBA') -> Genera RGBA
  • convert('RGB') -> Genera RGB
Finalmente convertiremos RGBA a RGB como paso previo a convertir la imagen de extensión png (con transparencias) a jpg (sin transparencias)...

# De RGBA a RGB
img_cv = img.convert('RGB')
print(img_cv.mode)                 -> Devuelve RGB
img_cv.show()
img_cv.save('img/grafcv.jpg') #Guardar imagen

... obteniendo el mismo efecto que antes (escala de grises) si realizamos la conversión inversa, aunque ahora la diferencia entre la original RGBA y la RGBA reformulada es menos evidente a la vista.

MAV. Python


Pillow

Usos básicos (III)


Ahora vamos a trabajar con el color, la luz y la nitidez. Para ello necesitamos algunos módulos, concretamente ImageChops,  ImageOps e ImageEnhance.

 

No será ésta la única entrada que dediquemos a esta temática, dado que se presentan múltiples opciones, lo cual puede tener el efecto negativo de distraernos de nuestros objetivos, ya que sobrepasa de largo nuestras necesidades pero resulta muy atrayente. Trataré de minimizar este efecto, pero difícil será no caer en excesos.

Para no empezar pecando de palabrería, presento el script donde desarrollo cómo generar ciertos efectos relativos al color, la luminosidad y la nitidez. Después comentaré algunas cuestiones. Por cierto, la fuente está disponible en [este enlace]. Te recomiendo visualizarlo.

from PIL import Image, ImageChops, ImageEnhance, ImageOps

#Cargar imagen base
img_dir = 'img/grafico.jpg'
img = Image.open(img_dir)

#Leer sus atributos
print(img.format, img.size, img.mode)

#Ver imagen base
img.show()

#Modificaciones -------------------------------------------------------------

#Invertir colores
img_inv = ImageChops.invert(img)
img_inv.show()

#Escala de grises
img_gris = ImageOps.grayscale(img)
img_gris.show()

#Resaltar luces
img_luz = ImageEnhance.Brightness(img).enhance(5)
img_luz.show()

#Contraste
img_cont = ImageEnhance.Contrast(img).enhance(5)
img_cont.show()

#Disminuir nitidez
img_nitida = ImageEnhance.Sharpness(img).enhance(-10)
img_nitida.show()

Trato en él cinco efectos: la inversión del color, la conversión a escala de grises, la luminosidad, el contraste y la nitidez de la imagen. Para ello hacemos uso de los módulos ImageChops, ImageOps e ImageEnhance, éste último para las tres modificaciones de luz, contraste y nitidez mediante funciones que reciben como parámetro la imagen, pero con el añadido de una segunda función con un parámetro numérico de efecto ordinal o de grado de intensidad (del efecto).



jueves, 16 de octubre de 2025

MAV. Python


Pillow

Usos básicos (II)



Aprendimos a cargar y guardar una imagen, así que ahora nos toca aprender a realizar algunas manipulaciones que pueden sernos de utilidad cuando trabajamos con imágenes. Se me ocurren algunas.

   


Dando por resueltos los pasos previos y la carga de la imagen, empezaré por cambiar su tamaño (grande a pequeño, claro)...

img_pq = img.resize((400,300))
img_pq.show()
img_pq.save('img/paisaje_pq.png')

... para lo que empleamos la función resize() que contiene una tupla como parámetro, la cual define el tamaño de la imagen resultante (img_pq = img.resize((400,300)))

También disponemos de una función que genera directamente una imagen en miniatura, aunque también requiere definir el tamaño de esa miniatura.

mini = (100,100)
img.thumbnail(mini)
img.save('img/paisaje_mini.png')

Puede que necesitemos rotar la imagen, tarea para la que disponemos de varias funciones, posiblemente la más versátil rotate() que recibe como parámetro los grados de rotación.

img_giro = img.rotate(50)
img_giro.show()
img_giro.save('img/paisaje_giro.png')

También podemos rotar la imagen en espejo, aunque para ello necesitamos trabajar con el módulo ImageOps que deberemos importar (from PIL Import Image, ImageOps).

img_espejo = ImageOps.mirror(img)
img_espejo.show()
img_espejo.save('img/paisaje_espejo.png')

Otra acción que nos puede interesar es recortar un trozo de la imagen. Para ello definimos una tupla indicando la zona a recortar y después aplicamos la función crop(), usando la tupla como parámetro.

zona = (100,100,500,500)
parte_img = img.crop(zona)
parte_img.show()
parte_img.save('img/paisaje_parte.png')

Finalmente vamos a unir dos imágenes mediante el método paste(). Este procedimiento requiere una explicación un poco más elaborada que los anteriores, por lo que lo voy a presentar en un script nuevo.

from PIL import Image

#Creamos la imagen de base

final = Image.new("RGB",(1800,1600),"black")

#Cargar primera imagen

img_dir1 = 'img/paisaje.png'

img_a = Image.open(img_dir1)

#Cargar segunda imagen

img_dir2 = 'img/cara.png'

img_b = Image.open(img_dir2)

#Pegamos las imágenes

final.paste(img_a,(0,650))

final.paste(img_b,(1000,0))

#Mostramos la imagen resultante y la guardamos 

final.show()

final.save('img/unir.png')

Observa que empezamos creando una imagen (con función de contenedor, en realidad) mediante el método new() (final = Image.new("RGB",(1800,1600),"black")), el cual requiere varios parámetro: el sistema de color ("RGB"), el tamaño ((1800,1600)) y el color de fondo ("black").

Después cargamos las dos (en este caso) imágenes que deseamos unir (vg. img_a = Image.open(img_dir1)) y las pegamos sucesivamente sobre el contenedor (vg final.paste(img_a,(0,650))), para lo que empleamos el método paste() que recibe como parámetros la imagen a pegar (img_a) y la posición en la que se sitúa su ángulo superior izquierdo ((0,650)).

Espero que estas manipulaciones te sean de interés. Pillow dispone de muchas más, algunas de las cuales veremos en próximas entradas.



MAV. Python

Pillow

Usos básicos (I)



Aunque es una biblioteca relativamente simple y limitada en cuanto a prestaciones (de ahí lo limitado de su uso), me ha parecido interesante incluirla en este blog precisamente por su sencillez, que nos proporciona un buen acercamiento al tema y nos provee de herramientas, algunas de ellas disponibles como utilidades de servicios (Impress, por ejemplo), pero que mediante Pillow podemos manejar con mayor eficiencia, además de proporcionarnos medios para automatizar ciertos procedimientos que, de otro modo, deberemos realizar "manualmente".


    

Parece evidente que lo primero que tendremos que aprender es a cargar y a guardar una imagen, pero para ello, antes tendremos que tener disponible la biblioteca. Procedamos.

from PIL import Image
#Cargar la imagen
img_dir = 'img/paisaje.png'
img = Image.open(img_dir)

#Leer algunos de sus atributos

print(img.format, img.size, img.mode)

#Visualizar la imagen

img.show()

#Guardar imagen

img.save("img/paisaje2.png")

No es mucho lo hecho, pero sí importante: accedemos y cargamos la imagen en memoria (img = Image.open(img_dir)), realizamos alguna manipulación elemental, por eso de hacer algo, como visualizarla (img.show()) y terminamos el script guardando una copia de la imagen (img.save("img/paisaje2.png")).

En la siguiente entrada nos dedicaremos a realizar algunas manipulaciones que sí tengan efecto sobre la imagen resultante, pero manteniendo como estrategia básica la consideración de la imagen como un todo. Existen otros planteamientos, pero aun es pronto para verlos.

MAV. Python

 Procesamiento básico de imágenes


Necesitamos trabajar con imágenes para muchas cosas y desde diferentes perspectivas, algunas muy básicas, como su manejo como documentos o como la simple traslación "a lo digital" de procedimientos manuales, incluyendo el corta-pega y similares. A todo esto (y a más, pero a esto fundamentalmente) es a lo que vamos a llamar procesamiento básico de imágenes.


Disponemos de varias herramientas en Python que, en lo que nos proponemos ahora, sirven para lo mismo, pero que se diferencian en procesamientos de mayor complejidad y especificidad. En esta subsección nos vamos a limitar a dos: Pilow y OpenCV. Con ambas vamos a construir lo que podríamos llamar una navaja multiusos para el manejo básico de imágenes.

La primera, Pilow, es la más sencilla (de instalar y usar), pero sobradamente útil. Puedes acceder a su documentación oficial [desde este enlace], incluye un interesante manual on-line. Y desde [aquí] un mini-curso en YouTube.

La biblioteca OpenCV no es Python en sentido estricto, pero puede ser usada mediante este lenguaje. Su instalación no es más complicada que la de Pilow, pero sí su uso, claro que en consonancia con su potencia y posibilidades de uso. Para descargarla accedemos a [esta página] y [este enlace]  te lleva a un mini-tutorial en You Tube.

En las próximas entradas iremos desarrollando algunas opciones de manejo de imágenes que nos proporcionan ambas bibliotecas. La intención no es tratarlas en profundidad (eso queda para ti en función de tus intereses), pero sí disponer, al final del proceso, de un conjunto de recursos de utilidad para que puedas manejar las imágenes que pudieras necesitar para el desarrollo de tus recursos.