Full Movie In One Shot

The article "Final cut: films condensed into a single frame – in pictures" in The Guardian tells us about the photographer Jason Shulman who captured the entire duration of a movie in a single image.

Inspired by the article, I decided to reproduce results, but computationally. I didn't expose the movies in front of a camera. Instead, I wrote a small program in python which stacks all frames from the given video file into a single picture. The process is essentially an equivalent to a single shot with an ultra-long exposure of the film.

The resulted picture often looks like a gray rectangle and requires color correction (playing a bit with levels in Gimp or Photoshop).

The screenshot of the article on The Guardian's website.
"Howl's Moving Castle" by Hayao Miyazaki, captured in a single image.
"Howl's Moving Castle" by Hayao Miyazaki, captured in a single image.
"The Matrix Revolutions" by Lana and Lilly Wachowski, captured in a single image.
"The Matrix Revolutions" by Lana and Lilly Wachowski, captured in a single image.
"Monsters, Inc" by Pete Docter, David Silverman, and Lee Unkrich, captured in a single image.
"Kill Bill: Vol. 2" by Quentin Tarantino, captured in a single image.
"Kill Bill: Vol. 2" by Quentin Tarantino, captured in a single image.
"The Dark Knight" by Christopher Nolan, captured in a single image.
"The Dark Knight" by Christopher Nolan, captured in a single image.
"WALL·E" by Andrew Stanton, captured in a single image.

The source code of my utility. The OpenCV library automated all the hard work. The program is just a sum of matrixes (frames / images).

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import click
from clickclick import AliasedGroup

import cv2
import numpy as np
from tqdm import tqdm

CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])

@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS)
def cli():
    """
    Stacks all video frames into one picture.
    Idea: https://www.theguardian.com/artanddesign/gallery/2017/may/16/jason-shulman-films-condensed-into-a-single-photo-frame-in-pictures
    """


@cli.command(help="stacks all video frames into one picture, technically converts video into one picture")
@click.argument("film")
@click.argument("output-image")
@click.argument("scale", type=float)
def convert(film, output_image, scale):
    # Opens the Video file
    capture = cv2.VideoCapture(film)

    stacked_image = None
    frames = 0
    total_frames = capture.get(cv2.CAP_PROP_FRAME_COUNT)
    frames_limit = int(total_frames * 0.9)

    with tqdm(total=frames_limit) as progress_bar:
        while capture.isOpened() and frames < frames_limit: # frames limit - we don't want to have titles in the final image
            ret, image = capture.read()
            if not ret:
                break

            image = cv2.resize(image, None, fx=scale, fy=scale)
            image = image.astype(np.float32) / 255
            if stacked_image is None:
                stacked_image = image
            else:
                stacked_image += image

            frames += 1
            progress_bar.update(1)

    stacked_image /= frames
    stacked_image = (stacked_image*255).astype(np.uint8)

    cv2.imwrite(output_image, stacked_image)
    capture.release()
    cv2.destroyAllWindows()


if __name__ == "__main__":
    cli()

Jul 7, 2019. Berlin