How to add GIF to a static background (Python + OpenCV). Video Generation series (Part 1)

A bad solution (with Pillow) and a good solution (with OpenCV).

Contents:

  • Bad Solution
  • Good Solution
  • Plans for this series

Bad Solution

My original approach was making another gif. I had to expect it was a bad idea as I wanted to merge a colorful JPEG background and an animated GIF.

The source data – the background (left) and a GIF (right) to put on top of it.

So I used Pillow:


from PIL import Image, ImageSequence


background = 'data/background.jpg'
gif = 'data/intro.gif'
background = Image.open(background).convert("RGBA")
animated_gif = Image.open(gif)
fps = animated_gif.info['duration']

frames = []
for frame in ImageSequence.Iterator(animated_gif):
    frame = frame.convert("RGBA")

     clear_background = background.copy()
     clear_background.paste(frame, mask=frame)
     frames.append(clear_background)
          frames.append(clear_background)

frames[0].save('output.gif', save_all=True, append_images=frames)

And as a result I got this:

Generated GIF (background converted to RGBA)

It has decent FPS, but the number of colors is too low. It is typical and was to be expected.


However, if I change line 3 to:

    background = Image.open(background) # .convert("RGBA")

Then the overall result changes, but it still corrupts the background:

Generated GIF (background NOT converted to RGBA)

See the difference between the original, RGBA and non-RGBA:

Original background and two (RGBA and non-RGBA) GIFs comparisons

And of course they all are heavy af – all GIFs are.

Good Solution

I was too involved in the process of making the PIL script work I got carried away and spent too much time of what looked like a vain idea.

Let’s get back to our beloved OpenCV and try and find a solution for it.

First of all, we need to make a video that consists of just the background image:

import cv2


background_image = 'data/background.jpg'
gif_image = 'data/intro.gif'

# load the background picture nad get width/height
background = cv2.imread(background_image)
background = background.astype(float)
height, width, color = background.shape

# set up the final video with 25 fps
video_destination = 'clips/intro.avi'
video = cv2.VideoWriter(video_destination, 0, 25, (width, height))

# open GIF
gifcap = cv2.VideoCapture(gif_image)

# iterated GIF frames and add it to the background while the GIF lasts
while gifcap.isOpened():
    ret, frame = gifcap.read()

    if ret:
        output = frame.copy()
        foreground = output.astype(float)
        output = cv2.add(foreground, background).astype(np.uint8)
        video.write(output)
    else: break

# close the GIF
gifcap.release()
# close the resulting video
video.release()

This became easy once I found the cv2.add(foreground, background) method.

As a result I got a perfectly good video. The result you see below is a GIF I generated from the video I got (as WordPress does not let me upload a video unless I pay them $100 – tough luck). The quality is not ideal.

Plans for this series

The next posts in the series will be about

  1. Making a small GIF out of a big video (like the result you see above).
  2. Resizing videos
  3. Adding a GIF on the foreground of a video (or GIF) background.
  4. Lowering the size of videos with python-ffmpeg.

3 thoughts on “How to add GIF to a static background (Python + OpenCV). Video Generation series (Part 1)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.