Long Exposure with Python and OpenCV

Kelvin Salton do Prado
4 min readJul 11, 2019
Image from Pixabay: https://pixabay.com/pt/photos/rua-noite-cidade-urbanas-luzes-371222/

In this story, we will learn about the long exposure photography technique and how to simulate it using Python and OpenCV (Open Source Computer Vision Library).

What is “long exposure”?

Directly from Wikipedia:

Long-exposure, time-exposure, or slow-shutter photography involves using a long-duration shutter speed to sharply capture the stationary elements of images while blurring, smearing, or obscuring the moving elements. Long-exposure photography captures one element that conventional photography does not: an extended period of time.

So, long exposure is a gorgeous photography technique which consists of creating an image that shows the effect of time, what ordinary photography does not capture. This kind of technique is not so easy for a beginner photographer since it requires a methodical approach to capture the images.

Luckily, we can simulate this technique using image processing. To do so, we can use a video, which is basically a series of images, to calculate the average image based on all (or almost all) video frames.

Dependencies

In this tutorial, we will use Python 3 and OpenCV.

We will use OpenCV because it is a well-known open-source computer vision library which provides many features to work with images and videos. In this tutorial, we will use OpenCV to manipulate the video and its frames.

The following image gracefully explains why we will use Python:

Made with https://imgflip.com/memegenerator/Creepy-Condescending-Wonka

Furthermore, we will use two other Python packages:

  • click: to provide a command-line interface (CLI).
  • tqdm: to show an elegant progress bar in the terminal.

We will also use Pipenv to create and manage a virtual environment easily.

Environment

The code related to this tutorial is available on Github, so go on and clone/fork it.

Using the Pipfile provided in the root of the project we can use Pipenv to create, install the dependencies and activate the virtual environment with the following commands:

pip install pipenv # if not installed yet
pipenv install --dev
pipenv shell

Code

Let’s start looking at the “entry point”. It is a CLI command where we should pass some arguments:

  • video_path: the path for the video in your local machine.
  • image_path: the path and filename of the output image.
  • — step/-s (optional): step used to get the frames. This is an optional argument and the default value is 1.

It uses click decorators to provide a beautiful command-line interface. If you don’t know click yet I really recommend you to take a look at the package.

This allows us to call the Python script like this:

python src/long_exposure.py local-video video.mp4 image.png -s 5

If you have doubts on how to use it, you can call it passing the help flag:

python src/long_exposure.py --help

Now, let’s talk about the LongExposure class. This is the main class of the project and it receives the following arguments in its __init__:

  • video: the video path in the local machine.
  • output_image_path: path/filename where the output image must be saved.
  • step: step used to ignore some frames (default 1). It is very useful for long videos.

The averager method is just a clojure which is used to incrementally calculate the average image as we are consuming the video frames one by one (this example can be seen in the Fluent Python book 😄).

As this is a callable class, the __call__ method is the main method of the class and it is basically responsible for:

  • load the video;
  • iterate by the video frames to calculate the average image (for each color channel);
  • merge the color channels and;
  • save the image on disk.

Note that cv2 is from OpenCV and the tqdm (in the loop) is just used to show the progress bar.

As you can see, there is no magic here, the code is really simple and almost explains by itself. Now, let’s see the results.

Results

I have used the following YouTube video to apply the long exposure effect:

Relax 3 Minutes — Waterfall and Relaxing Birds Singing

(note that I cut the end of the video where some ads appeared)

And you can see the final result here (using step of 20):

What a wonderful picture 😍

Final notes

The project is available on Github, feel free to contribute ❤️

If you have any questions, feel free to ask here, to open a Github issue or to contact me.

As the project is open source and the code is hosted on Github it will probably change in the future, so please get the update code there.

If you liked this story please give it a clap 👏 and share it. It motivates me to write more stories.

References

--

--