Capture video from camera/file with OpenCV in Python
In Python, you can read, capture, and display video files and camera stream using the VideoCapture
class with OpenCV. Note that Video I/O
must be enabled in OpenCV to process video.
This article describes the following contents.
- Requires
Video I/O
enabled to handle video in OpenCV - Read video:
VideoCapture()
- Read video files
- Capture video from camera stream
- Close video
- Get and set video properties (size, FPS, number of frames, etc.)
- Get video properties:
get()
- Set video properties:
set()
- Get video properties:
- Get frame images in NumPy array
ndarray
- For video files
- For camera
- Play video
- Repeat playback of video file
- Display real-time video from camera
- Real-time image processing
The tutorial on video in the official documentation is below.
The OpenCV version of the sample code is 4.0.1
.
See the following article for information on reading and writing still images, not videos.
Requires Video I/O
enabled to handle video in OpenCV
Video I/O
must be enabled to handle video in OpenCV. If an error occurs and the video cannot be loaded, you should first check to see if Video I/O
is enabled.
You can check OpenCV build information with getBuildInformation()
.
How to build with Video I/O
enabled varies depending on the environment, and is not discussed here.
For macOS, if you install OpenCV with Homebrew, ffmpeg will be installed at the same time and Video I/O
will be enabled (as of January 27, 2019).
Read video: VideoCapture()
Create a VideoCapture
object with VideoCapture()
to handle video.
Read video files
To read a video file, specify the path to the file in VideoCapture()
. It can be an absolute path or a relative path.
You can check if it is successfully read with the isOpened()
method. If there is no problem, True
is returned.
import cv2
cap_file = cv2.VideoCapture('data/temp/sample_video.mp4')
print(type(cap_file))
# <class 'cv2.VideoCapture'>
print(cap_file.isOpened())
# True
Note that VideoCapture()
does not raise an error if a wrong path is specified. You should check with isOpened()
.
cap_file_wrong = cv2.VideoCapture('wrong_path')
print(type(cap_file_wrong))
# <class 'cv2.VideoCapture'>
print(cap_file_wrong.isOpened())
# False
Capture video from camera stream
To capture video from a PC's built-in camera or a USB camera/webcam, specify the device index in VideoCapture()
.
In most cases, the device index is assigned from 0
, such as 0
for the built-in camera and 1
for additional cameras connected via USB.
According to the tutorial in the official documentation, there are cases where it is -1
.
Anyway, you can try them in order.
An API to get a list of available cameras is not yet provided (as of January 27, 2019).
You can check with the isOpened()
method to see if the camera is successfully specified, just as you would with a video file.
import cv2
cap_cam = cv2.VideoCapture(0)
print(type(cap_cam))
# <class 'cv2.VideoCapture'>
print(cap_cam.isOpened())
# True
Note that, as with video files, VideoCapture()
does not raise an error if an incorrect device index is specified.
cap_cam_wrong = cv2.VideoCapture(1)
print(type(cap_cam_wrong))
# <class 'cv2.VideoCapture'>
print(cap_cam_wrong.isOpened())
# False
Close video
You can close video files and camera devices with the release()
method.
cap_cam.release()
Get and set video properties (size, FPS, number of frames, etc.)
Get video properties: get()
You can get the properties of the opened video with the get()
method of the VideoCapture
object.
The following sample video is used as an example. Sorry for the Japanese site, but if you check the checkbox in the lower right corner, you can download the file from the blue button.
import cv2
cap = cv2.VideoCapture('data/temp/sample_video.mp4')
print(type(cap))
# <class 'cv2.VideoCapture'>
print(cap.isOpened())
# True
Specify the property as an argument of the get()
method.
For example, you can get the size (width and height), FPS (frames per second), and total number of frames as follows:
print(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
# 640.0
print(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 360.0
print(cap.get(cv2.CAP_PROP_FPS))
# 29.97002997002997
print(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# 360.0
You can calculate the playback time of the video in seconds with Total frames / FPS
.
print(cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap.get(cv2.CAP_PROP_FPS))
# 12.012
See the official documentation for a list of property identifiers.
Note that if you use OpenCV2, you need to prefix it with CV_
.
The example above uses a video file, but the same is true for a camera stream. However, there are some differences, such as the total number of frames is not set (always 0
) because the camera is real-time video.
Set video properties: set()
Some properties can be set to a value with the set()
method. Specify the property as the first argument and the value as the second argument.
set()
returns True
or False
. If it cannot be changed, False
is returned. In this case, the value remains the same.
print(cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320))
# False
print(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
# 640.0
If the value can be changed, True
is returned.
print(cap.get(cv2.CAP_PROP_POS_FRAMES))
# 0.0
print(cap.set(cv2.CAP_PROP_POS_FRAMES, 100))
# True
print(cap.get(cv2.CAP_PROP_POS_FRAMES))
# 100.0
CAP_PROP_POS_FRAMES
property represents the current position of the video. Details are described below.
Note that even if set()
returns True
, the value may not be changed. For example, set()
is used to change the FPS of a camera, but if the camera itself does not support that FPS, the value may not be changed even if set()
returns True
.
Get frame images in NumPy array ndarray
You can get the frames of the video as a NumPy array ndarray
with the read()
method of the VideoCapture
object.
For video files
For video files, you need to consider the current position.
You can get the current number of frames and the elapsed time in milliseconds with the get()
method. Both are 0
when the file is opened.
import cv2
cap = cv2.VideoCapture('data/temp/sample_video.mp4')
print(type(cap))
# <class 'cv2.VideoCapture'>
print(cap.isOpened())
# True
print(cap.get(cv2.CAP_PROP_POS_FRAMES))
# 0.0
print(cap.get(cv2.CAP_PROP_POS_MSEC))
# 0.0
Call the read()
method here.
read()
returns a tuple consisting of bool
indicating if the frame was successfully read or not and ndarray
, the array of the image. You can assign to each variable with unpacking.
ret, frame = cap.read()
print(ret)
# True
print(type(frame))
# <class 'numpy.ndarray'>
print(frame.shape)
# (360, 640, 3)
If you want to save a frame image or do something, you can do it to this ndarray
.
When the read()
method is executed, the current position is advanced by one frame. The elapsed time of one frame is equal to the reciprocal of FPS.
print(cap.get(cv2.CAP_PROP_POS_FRAMES))
# 1.0
print(cap.get(cv2.CAP_PROP_POS_MSEC))
# 33.36666666666667
print(1 / cap.get(cv2.CAP_PROP_FPS) * 1000)
# 33.36666666666667
You can move the current position to any frame with the set()
method.
cap.set(cv2.CAP_PROP_POS_FRAMES, 100)
print(cap.get(cv2.CAP_PROP_POS_FRAMES))
# 100.0
If read()
is called here, the current position is advanced by one frame.
ret, frame = cap.read()
print(ret)
# True
print(cap.get(cv2.CAP_PROP_POS_FRAMES))
# 101.0
print(cap.get(cv2.CAP_PROP_POS_MSEC))
# 3370.0333333333333
If the current position is set to the total number of frames, read()
returns False
and None
since no more frames exist. In this case, the current position does not advance and remains at the end.
cap.set(cv2.CAP_PROP_POS_FRAMES, cap.get(cv2.CAP_PROP_FRAME_COUNT))
print(cap.get(cv2.CAP_PROP_POS_FRAMES))
# 360.0
ret, frame = cap.read()
print(ret)
# False
print(frame)
# None
print(cap.get(cv2.CAP_PROP_POS_FRAMES))
# 360.0
If a value greater than the total number of frames is set, the current position is still at the end.
cap.set(cv2.CAP_PROP_POS_FRAMES, 1000)
print(cap.get(cv2.CAP_PROP_POS_FRAMES))
# 360.0
For camera
In a live stream from a camera, new frames are constantly input. Unlike files, the camera has no current position, and CAP_PROP_POS_FRAMES
always returns 0
.
When read()
is called, the image of the newly input frame is read.
import cv2
cap_cam = cv2.VideoCapture(0)
print(type(cap_cam))
# <class 'cv2.VideoCapture'>
print(cap_cam.isOpened())
# True
print(cap_cam.get(cv2.CAP_PROP_POS_FRAMES))
# 0.0
ret, frame = cap_cam.read()
print(ret)
# True
print(type(frame))
# <class 'numpy.ndarray'>
print(frame.shape)
# (720, 1280, 3)
print(cap_cam.get(cv2.CAP_PROP_POS_FRAMES))
# 0.0
Play video
OpenCV does not provide any method to play (display) videos.
You can display images loaded with read()
sequentially with imshow()
. Since this is only a display of images, audio is ignored.
Repeat playback of video file
An example of repeated playback of a video file is as follows. Press q
to exit.
import cv2
import sys
file_path = 'data/temp/sample_video.mp4'
delay = 1
window_name = 'frame'
cap = cv2.VideoCapture(file_path)
if not cap.isOpened():
sys.exit()
while True:
ret, frame = cap.read()
if ret:
cv2.imshow(window_name, frame)
if cv2.waitKey(delay) & 0xFF == ord('q'):
break
else:
cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
cv2.destroyWindow(window_name)
Using an infinite loop with a while
statement, the image will continue to be read and displayed until q
on the keyboard is pressed.
When the video is played to the end, the set()
method sets the current position to 0
(the start position of the video).
If you want to play the video only once without looping, set break
after else
.
waitKey()
stops operation for a specified time (in milliseconds) and waits for keyboard input. If waitKey()
is set to 0
, it waits until keyboard input, so the displayed image is not updated until some key is pressed. The image is updated when a key other than q
is pressed.
destroyWindow()
closes the window with the specified name. destroyAllWindows()
, which closes all windows, is also provided.
The release()
method is automatically called in the destructor of the VideoCapture
object, so it is omitted here. If the code continues after this, it may be safer to close it explicitly with release()
.
Display real-time video from camera
An example of real-time video playback from a camera is as follows. Press q
to exit.
import cv2
import sys
camera_id = 0
delay = 1
window_name = 'frame'
cap = cv2.VideoCapture(camera_id)
if not cap.isOpened():
sys.exit()
while True:
ret, frame = cap.read()
cv2.imshow(window_name, frame)
if cv2.waitKey(delay) & 0xFF == ord('q'):
break
cv2.destroyWindow(window_name)
If the camera is unstable, some frames cannot be read by read()
and (False, None)
may be returned. In such a case, use if ret
to check if the frame is read correctly.
Real-time image processing
To process images from a camera in real-time, you can add operations between read()
and imshow()
.
An example of grayscale conversion and blurring processing is as follows.
import cv2
import sys
camera_id = 0
delay = 1
window_name = 'frame'
cap = cv2.VideoCapture(camera_id)
if not cap.isOpened():
sys.exit()
while True:
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (0, 0), 5)
cv2.imshow(window_name, blur)
if cv2.waitKey(delay) & 0xFF == ord('q'):
break
cv2.destroyWindow(window_name)