Optical illusions

I've stumbled across the quite cool Youtube video below that is about an optical illusion that is very easy to reproduce just printing a copuple of images.

The idea seems to be quite simple.

The first image can be obtained by taking every frame of an animation, cutting it into vertical stripes, interleaving the stripes and sticthing them together.

The second image is essentialy a mask obained using the same approach, starting from an animation with the same number of frames of the original one, but made with a white frame, followed by black frames.

By interleaving I mean that once you have sliced the $N$ frames, you create a first block of stripes taking stripe $0$ from the first frame, then stripe $1$ from the second frame and so on so forth up to stripe $N-1$ from the last frame; then you start the second block of stripes by taking stripe $N$ from the first frame, stripe $N+1$ from the second frame and so on. Finally you stitch the blocks together.

The source notebook is available on GitHub (under GPL v3), feel free to use issues to point out errors, or to fork it to suggest edits.

A simple example

Let's try to make it more clear with an example. Consider an animation with three frames, containing the first capital letters of the alphabet suitably colored.

To define the function performing the interleaving we'll use quite a few tricks.

First of all, given the width of the stripes, we generate the indexes where we want to slice the frames.

Then, using numpy.hsplit we cut every frame in a list of stripes. For example, for the first frame we get

For the $k$-th frame, we keep just one stripe every len(frames), that is we use [k::len(frames)] to index the list of stripes of frame $k$. We collect all such list of stripes in a list.

Again, for the first frame, we keep just the first and fourth stripes

Once we have such a list we zip it and use numpy.hstack to stitch together one stripe per frame obaining blocks of $N$ stripes each, finally we again use numpy.hstack to stitch every block together.

We are ready to put together our tricks.

Let's test it with a smaller width

It's easy to note that there is no overlap among frames; since we have choosen red, green and blue, we can watch at a channel at a time to check this

A more realistic example

To produce a more interesting result, let's start from an animated GIF; we need first of all to extract the frames.

As an example, I choose a waling duck.

Since such GIF contains too many frames and every frame has a lot of white space around the main subject, we pick a frame every 3 and crop it.

The mask

As promised, generating the mask is quite easy, you just need a white and a black frames.

You can now print the two images and try if it works!