Capture video from camera/file with OpenCV in Python

Posted: | Tags: Python, OpenCV

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 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)

Related Categories

Related Articles