Saltar al contenido

Creación de GIF animado con imageio y Python

Muchas veces miro el tiempo, me dedico a ello, a mirar las nubes. No estoy en babia, es mi trabajo 🙂

Para ello, muchos días miro la página de la aemet, entre otras muchas. Y muchos días pienso que la información disponible podría ser bastante mejor.

Por ejemplo, las imágenes de las descargas de rayos solo están disponibles, desde la página web, las últimas seis horas (+6 horas que incluye cada imagen). Si vamos a su ‘genial’ API el panorama es incluso peor:

  • necesitas una clave para acceder.
  • para obtener una clave necesitas meter un correo y resolver un odioso reCaptcha.
  • te mandan un correo que tienes que abrir y confirmar la petición.
  • te mandan un segundo correo con la clave.
  • accedes a la API y parece que solo puedes descargar la última imagen de descargas de rayo…

Es decir, desde la API obtienes menos información y el proceso es mucho más engorroso.

(todo lo anterior no tiene nada que ver con este artículo pero me ha servido para descargar mi frustración momentánea)

Pero, por lo visto, haciendo un poco de artimañas, desde la web se puede acceder a más información, a más imágenes. Vamos a usar esas imágenes para hacer el GIF animado.

La url de las imágenes estáticas tiene este formato:

http://www.aemet.es/imagenes_d/eltiempo/observacion/rayos/201912131600_r79g.gif

La parte interesante es esta: 2019121316. Ahí se define la fecha de la imagen (AAAAMMDDHH) donde AAAA es para año, MM es para mes, DD es para día y HH es para hora. Podemos usar un par de bibliotecas de la stdlib para descargar todas las imágenes que nos deje usando el siguiente código:

import datetime as dt
from urllib.request import urlretrieve

_dt = dt.datetime.utcnow()
while True:
    url = (
        "http://www.aemet.es/imagenes_d/eltiempo/observacion/rayos/"
        f"{_dt.strftime('%Y%m%d%H')}"
        "00_r79g.gif"
    )
    print(url)
    try:
        fn, r = urlretrieve(url, f"{_dt.strftime('%Y%m%d%H')}00_r79g.gif")
        _dt = _dt - dt.timedelta(hours=1)
    except:
        break

El código anterior coge la hora actual en UTC y crea un bucle infinito en el que empieza a descargar las imágenes disponibles que haya. Si no encuentra una imagen sale del bucle infinito. El código anterior es muy simple y podría fallar de muchas formas. Por ejemplo, si la hora inicial que usamos, _dt, es superior a la hora de la última imagen disponible fallará y no descargará nada. Te dejo como ejercicio hacer el código anterior más robusto 😛

Corriendo ese código, ahora en invierno, con UTC+1 (Península y Baleares), no me ha fallado y me ha descargado más de 100 imágenes, en la carpeta en la que se encuentre el programa, en lugar de solo las seis imágenes que tenemos disponibles desde la web.

Con esas imágenes vamos a hacer un GIF animado usando imageio. No voy a contar gran cosa de esta biblioteca, tienes la documentación para ello. Pero vamos a ver como con unas pocas líneas podemos generar el GIF animado. El código, sumado al código anterior, quedará de la siguiente forma:

import datetime as dt
from urllib.request import urlretrieve
from glob import glob

import imageio

_dt = dt.datetime.utcnow()
while True:
    url = (
        "http://www.aemet.es/imagenes_d/eltiempo/observacion/rayos/"
        f"{_dt.strftime('%Y%m%d%H')}"
        "00_r79g.gif"
    )
    print(url)
    try:
        fn, r = urlretrieve(url, f"{_dt.strftime('%Y%m%d%H')}00_r79g.gif")
        _dt = _dt - dt.timedelta(hours=1)
    except:
        break

filenames = sorted(list(glob("*.gif")))
imgs = []
for f in filenames:
    imgs.append(imageio.imread(f))
imageio.mimsave('rayosanimados.gif', imgs, duration=0.1, subrectangles=True)

En el nuevo código, lo que hacemos es leer las imágenes que habíamos descargado usando imageio. Cada vez que leemos una imagen nos devuelve un numpy array que almacenamos en una lista. Cuando ya hemos leído todas las imágenes usamos mimsave para crear el GIF animado. Los parámetros que uso son el nombre del GIF animado final, la lista con las imágenes, la duración de cada fotograma y, lo último, pretende que la imagen ocupe menos pero no hace un gran trabajo en este caso. La animación que nos queda es bastante pesada comparada con lo que pesaban las imágenes iniciales. Hay formas de resolver esto pero ahora no vamos a entrar. El artículo solo pretende mostrar una forma muy sencilla de crear el GIF animado.

El resultado lo podéis ver a continuación:

Espero que le resulte útil a alguien.

Hasta la próxima.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

six + three =

Pybonacci