I am working with this data analysis pipeline that makes gifs of video recordings, the function used for this is:
def make_gif(self, datafile, save_file, frame_limit:int=20, fps:int=10, verbose=True):
h5 = h5py.File(datafile, "r")
frames = h5['frames'][::2][:frame_limit]
imageio.mimwrite(save_file, frames, fps=fps)
if verbose:
print(f"Saved gif version: fps={fps}, nframes={frame_limit}", flush=True)
The only necessary imports for this are h5py
and imageio
.
I'm needing to append some text to these gifs. There's some metadata we need displayed for quick reading. For example, I have a stack of frames that look like this image:
But what I need is something like this:
How would I go about doing that with Python and imageio? I should note that I cannot save the individual images as jpgs for reuploading later, I need to create the gifs as part of the pipeline.
Our focus with ImageIO is on the IO side of images. If you want to add text to an image or perform any other processing of the image, you will want to bring in an image processing library. Common choices here are scikit-image
or opencv
.
Here is an example of how you can do this using cv2
. Note that I am using a standard image here for better reproducibility, but the same logic works with HDF5 and other video/image formats.
import imageio.v3 as iio
import cv2
frames = iio.imread("imageio:newtonscradle.gif") # example image/frames
# add the text
for frame in frames:
foo = cv2.putText(
frame,
"Hey look some metadata",
(5, 25),
cv2.FONT_HERSHEY_SIMPLEX,
.4,
(0, 0, 0)
)
# write the output
iio.imwrite("annotated.gif", frames, loop=0)
Output:
Weirdly, scikit-image
doesn't allow rendering text onto an image, but there is an age-old issue to track that feature here.
Alternatively, if visualization is what you are after, you could use matplotlib
. This comes with the advantage of giving you all the power of the MPL but comes with the drawback of losing control over individual pixels. This is not ideal for scientific processing (where pixel values matter), but great for quick annotations, human consumption, and qualitative data.
Here is an example how you could recreate the above:
import imageio.v3 as iio
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.figure import figaspect
frames = iio.imread("imageio:newtonscradle.gif")
aspect_ratio = figaspect(frames[0, ..., 0])
annotated_frames = list()
for frame in frames:
fig, ax = plt.subplots(figsize=aspect_ratio, dpi=50)
ax.imshow(frame)
ax.text(5, 5, "Hey look some metadata", fontsize="xx-large", va="top")
ax.set_axis_off()
ax.set_position([0, 0, 1, 1])
fig.canvas.draw()
annotated_frames.append(np.asarray(fig.canvas.renderer.buffer_rgba()))
plt.close(fig)
iio.imwrite("annotated.gif", annotated_frames, loop=0)
Output: