Extracting Frames FAST from a Video using OpenCV and Python
UPDATE (JUL 2020): I now use, and suggest the use of decord for faster video loading in Python. You can view the original OpenCV only version further down. :)
Below is an example script of how to extract frames using decord. It has similarities to the OpenCV version but is faster, cleaner, and simpler. Take note that it extracts frames using either batch collection or sequential reading based on the every
parameter. I have set the threshold for 25
and the total
threshold to 1000
as this was what was appropriate for my system’s memory constraints and CPU abilities.
I’ve worked with videos a lot over the years and one thing that I often need to do is to extract the frames from a video and save them as individual images. Over time I have had to work with bigger and more error prone video files and have recently settled on a nice script that I thought I would share.
Let’s start with the basic function which can extract frames from a single video without too much effort. This function called extract_frames()
takes a video path, a path to a frames directory, and a few extras like whether we want to overwrite frames if they already exist, or only do every x many frames.
You might notice that we are using a while loop with a kinda odd looking while_safety
counter. This is there because sometimes OpenCV will return empty frames, in which case we want to just keep reading without incrementing theframe
counter. This increases any potential that already existed for an endless loop, which is why the while_safety
counter is used and incremented every time theframe
counter isn’t.
Although the above code is simple, it is actually pretty slow, it turns out extracting and saving frames takes a while. Luckily these days computers tend to have multiple CPU cores that can do things in parallel. So let’s extend upon the above code to add parallel processing over all CPU cores.
To do this we write a wrapping function video_to_frames()
that firstly breaks a video into chunks of length chunk_size
, and then calls the extract_frames()
funtion seen above on each chunk.
If you have any extra suggestions or comments let me know below, or via one of my channels.
With love,
Hayden