Today’s blog post is part of a two part series on working with video files using OpenCV and Python.
The first part of this series will focus on a question emailed in by PyImageSearch reader, Alex.
Alex asks:
I need to count the total number of frames in a video file with OpenCV. The only way I’ve found to do this is to loop over each frame in the video file individually and increment a counter. Is there a faster way?
Great question Alex.
And rest assured, you’re not the first person who has asked me this question.
In the remainder of this blog post I’ll show you how to define a function that can quickly determine the total number of frames in a video file.
Next week we’ll use this function to aid us in a fun visualization task where I’ll demonstrate how to create “movie barcodes”. In order to generate these movie barcodes we’ll first need to know how many frames there are in our input movie file.
To learn more about fast, efficient frame counting with OpenCV and Python, just keep reading.
Looking for the source code to this post?
Jump Right To The Downloads SectionCount the total number of frames in a video with OpenCV and Python
There are two methods to determine the total number of frames in a video file using OpenCV and Python:
- Method #1: The fast, efficient way using the built-in properties OpenCV provides us to access the video file meta information and return the total number of frames.
- Method #2: The slow, inefficient technique that requires us to manually loop over each frame and increment a counter for each frame we’ve read.
Method #1 is obviously ideal.
All we need to do is open a pointer to the video file, tell OpenCV which meta property we are interested, and get the returned value.
No looping over frames manually.
No wasted CPU cycles decoding frames.
…however, I’m sure you’ve realized there is a catch.
The problem here is that Method #1 is buggy as all hell based on your OpenCV version and video codecs installed.
You’ll find there are situations where more than half of the .get
and .set
methods on video pointers simply don’t work. In situations like these we’ll inevitably have to revert to Method #2.
So, is there a way to encapsulate both of these methods into a single function?
You bet there is.
I’ve already implemented the count_frames function inside the imutils library, but to ensure you’re understanding what’s going on under the hood we’ll be reviewing the entire function here today.
The easy way to count frames with OpenCV and Python
The first method to count video frames in OpenCV with Python is very fast — it simply uses the built-in properties OpenCV provides to access a video file and read the meta information of the video.
Let’s go ahead and see how this function is implemented inside imutils now:
# import the necessary packages from ..convenience import is_cv3 import cv2 def count_frames(path, override=False): # grab a pointer to the video file and initialize the total # number of frames read video = cv2.VideoCapture(path) total = 0 # if the override flag is passed in, revert to the manual # method of counting frames if override: total = count_frames_manual(video)
To start, we import our necessary Python packages on Lines 2 and 3. We’ll need the is_cv3
function to check which version of OpenCV we’re using along with cv2
for our actual OpenCV bindings.
We define the count_frames
function on Line 5. This method requires a single argument followed by a second optional one:
path
: This is the path to where our video file resides on disk.override
: A boolean flag used to determine if we should skip Method #1 and go directly to the slower (but guaranteed accurate/error free) Method #2.
We make a call to cv2.VideoCapture
on Line 8 to obtain a pointer to the actual video file followed by initializing the total
number of frames in the video.
We then make a check on Line 13 to see if we should override
. If so, we call count_frames_manual
(which we’ll define in the next section).
Otherwise, let’s see how Method #1 is actually implemented:
# otherwise, let's try the fast way first else: # lets try to determine the number of frames in a video # via video properties; this method can be very buggy # and might throw an error based on your OpenCV version # or may fail entirely based on your which video codecs # you have installed try: # check if we are using OpenCV 3 if is_cv3(): total = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) # otherwise, we are using OpenCV 2.4 else: total = int(video.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT)) # uh-oh, we got an error -- revert to counting manually except: total = count_frames_manual(video) # release the video file pointer video.release() # return the total number of frames in the video return total
In order to determine the number of frames in a video file via the API by provided by OpenCV, we need to utilize what are called capture properties, or what OpenCV calls CAP_PROP
— anytime you see a constant starting with CAP_PROP_*
, you should know it’s related to video processing.
In OpenCV 3 the name of the frame count property is cv2.CAP_PROP_FRAME_COUNT
while in OpenCV 2.4 the property is named cv2.cv.CV_CAP_PROP_FRAME_COUNT
.
Ideally, passing the respective property name into the .get
method of the video
pointer will allow us to obtain the total number of frames in the video (Lines 25-30).
However, there are cases where this method will fail based on your particular OpenCV install and video codecs.
If this is the case, we have wrapped our critical code section with a try/except
block. If an exception occurs we simply revert to counting the frames manually (Lines 33 and 34).
Finally, we release the video file pointer (Line 37) and return the total number of frames to the calling function (Line 40).
The slow way to count frames with OpenCV and Python
We’ve seen the fast, efficient method to counting frames in a video — let’s now move on to the slower method called count_frames_manual
.
# import the necessary packages from ..convenience import is_cv3 import cv2 def count_frames(path, override=False): # grab a pointer to the video file and initialize the total # number of frames read video = cv2.VideoCapture(path) total = 0 # if the override flag is passed in, revert to the manual # method of counting frames if override: total = count_frames_manual(video) # otherwise, let's try the fast way first else: # lets try to determine the number of frames in a video # via video properties; this method can be very buggy # and might throw an error based on your OpenCV version # or may fail entirely based on your which video codecs # you have installed try: # check if we are using OpenCV 3 if is_cv3(): total = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) # otherwise, we are using OpenCV 2.4 else: total = int(video.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT)) # uh-oh, we got an error -- revert to counting manually except: total = count_frames_manual(video) # release the video file pointer video.release() # return the total number of frames in the video return total def count_frames_manual(video): # initialize the total number of frames read total = 0 # loop over the frames of the video while True: # grab the current frame (grabbed, frame) = video.read() # check to see if we have reached the end of the # video if not grabbed: break # increment the total number of frames read total += 1 # return the total number of frames in the video file return total
As we can see, count_frames_manual
requires only a single argument, video
, which we assume to be a pointer instantiated by cv2.VideoCapture
.
We then initialize the total number of frames read from the video
file, loop over the frames until we have reached the end of the video, and increment the total
counter along the way.
The total
is then returned to the calling function.
It’s worth mentioning that this method is totally accurate and error free. If you do get an error it’s almost certainly related to a problem with your video codecs or an invalid path to a video file.
There also might be times when using this function you get a total of zero frames returned. When this happens it’s 99% likely that:
- You supplied an invalid path to
cv2.VideoCapture
. - You don’t have the proper video codecs installed and thus OpenCV cannot read the file. If this is the case you’ll need to install the proper video codecs, followed by re-compiling and re-installing OpenCV.
Counting frames in video files with OpenCV
Let’s go ahead and take our count_frames
method for a test drive.
To start, make sure you have installed the imutils library:
$ pip install imutils
Otherwise, if you already have imutils
installed you should update to the latest version (> v0.3.9):
$ pip install --upgrade imutils
From there, let’s create our driver script named frame_counter.py
:
# import the necessary packages from imutils.video import count_frames import argparse import os # construct the argument parse and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-v", "--video", required=True, help="path to input video file") ap.add_argument("-o", "--override", type=int, default=-1, help="whether to force manual frame count") args = vars(ap.parse_args())
We start by importing our required Python packages and parsing our command line arguments. We’ll require one switch followed by a second optional one:
--video
: The path to our input video file.--override
: Whether or not to force a manual frame count. We’ll try to use the faster Method #1 by default.
We then make a call to count_frames
and display the result to our screen:
# count the total number of frames in the video file override = False if args["override"] < 0 else True total = count_frames(args["video"], override=override) # display the frame count to the terminal print("[INFO] {:,} total frames read from {}".format(total, args["video"][args["video"].rfind(os.path.sep) + 1:]))
To test out this Python script, I’ve decided to use the trailer from my favorite movie, Jurassic Park:
How many frames do you think are in this video clip?
500?
5,000?
50,000?
Take your best guess and then let’s execute our Python script to find out.
Note: I used the website keepvid.com to download a .mp4 of the trailer. I do not own the copyrights to this movie or trailer. This script is only for demonstration and educational purposes. Please use responsibly.
To test out the fast method, execute the following command:
$ time python frame_counter.py --video videos/jurassic_park_trailer.mp4 [INFO] 4,790 total frames read from jurassic_park_trailer.mp4 real 0m0.803s user 0m0.176s sys 0m0.112s
As my results demonstrate, it takes 0.803s to determine there are a total of 4,790 frames in the video file.
We can test out the slower method using this command:
$ time python frame_counter.py --video videos/jurassic_park_trailer.mp4 --override 1 [INFO] 4,978 total frames read from jurassic_park_trailer.mp4 real 1m55.289s user 0m34.833s sys 0m7.988s
Here we see that it takes 1m55s (an increase of approximately 14,221%) to return a frame count of 4,978 which differs Method #1 by 188 frames.
Why the discrepancy in frame counts?
It all comes down to fast and approximate versus slow but accurate.
Using OpenCV’s video capture properties we get a total frame count very fast, but it might not be 100% dead on. We also have the potential of this method failing entirely due to OpenCV/video codec versioning.
On the other hand, if we manually count the number of frames it will take us a long time, but the total number of returned frames will be exact.
In situations where you absolutely, positively, must have the exact count, go with Method #2.
If you need a rough approximation, go with Method #1 (unless it fails, then you’ll be reverting back to Method #2 anyway).
What's next? I recommend PyImageSearch University.
30+ total classes • 39h 44m video • Last updated: 12/2021
★★★★★ 4.84 (128 Ratings) • 3,000+ Students Enrolled
I strongly believe that if you had the right teacher you could master computer vision and deep learning.
Do you think learning computer vision and deep learning has to be time-consuming, overwhelming, and complicated? Or has to involve complex mathematics and equations? Or requires a degree in computer science?
That’s not the case.
All you need to master computer vision and deep learning is for someone to explain things to you in simple, intuitive terms. And that’s exactly what I do. My mission is to change education and how complex Artificial Intelligence topics are taught.
If you're serious about learning computer vision, your next stop should be PyImageSearch University, the most comprehensive computer vision, deep learning, and OpenCV course online today. Here you’ll learn how to successfully and confidently apply computer vision to your work, research, and projects. Join me in computer vision mastery.
Inside PyImageSearch University you'll find:
- ✓ 30+ courses on essential computer vision, deep learning, and OpenCV topics
- ✓ 30+ Certificates of Completion
- ✓ 39h 44m on-demand video
- ✓ Brand new courses released every month, ensuring you can keep up with state-of-the-art techniques
- ✓ Pre-configured Jupyter Notebooks in Google Colab
- ✓ Run all code examples in your web browser — works on Windows, macOS, and Linux (no dev environment configuration required!)
- ✓ Access to centralized code repos for all 500+ tutorials on PyImageSearch
- ✓ Easy one-click downloads for code, datasets, pre-trained models, etc.
- ✓ Access on mobile, laptop, desktop, etc.
Summary
In this blog post I demonstrated two methods to count the number of frames in a video file using OpenCV and Python.
The first method is super quick, relying on OpenCV’s video property functionality, allowing us to (nearly) instantaneously determine the number of frames in a video file.
However, this method is quite buggy, is prone to failure (based on your OpenCV + video codec versions), and may even return nonsensical results.
In that case, we need to revert to our second method: manually counting the total number of frames in a video. While excruciatingly slow, this method has the advantage of being 100% accurate.
In order to balance speed versus potential failure I have created the count_frames
function and placed it inside the imutils library.
This function will attempt Method #1 first, and if it fails, automatically revert to Method #2.
In next week’s blog post we’ll be using this function to aid us in generating and visualizing video barcodes.
See you next week!
To be notified when the next blog posts goes live, be sure to enter your email address in the form below!
Download the Source Code and FREE 17-page Resource Guide
Enter your email address below to get a .zip of the code and a FREE 17-page Resource Guide on Computer Vision, OpenCV, and Deep Learning. Inside you'll find my hand-picked tutorials, books, courses, and libraries to help you master CV and DL!