Video Capture

Webcam Capture

Basic example showing how to open the webcam, show the video to the user and saving it to an output file.

import cv2

# Capture video from webcam
cap = cv2.VideoCapture(0)

# Output video
writer = cv2.VideoWriter("webcam.mp4", cv2.VideoWriter_fourcc(*'mp4v'), 25, (640, 480))

while(True):
    # Capture frame
    ret, frame = cap.read()
    # Write frame to the output file
    writer.write(frame)
    # Show the frame
    cv2.imshow("Webcam Capture", frame)
    # Break the loop when pressing "x" key
    if cv2.waitKey(1) &0XFF == ord('x'):
        break

cap.release()
writer.release()
cv2.destroyAllWindows()

There are a lot of problems in this code:

  • The device port number is set manually (0), in case of multiple devices, we need to be able to chose the webcam desired.

  • We don’t know the true native resolution of the webcam, it is set by default to 640x480. Also, we don’t know which resolutions are available/valid for this device.

  • The input framerate from the webcam is variable whereas we set it manually for the output video file.

List available devices

import cv2

ports_availables = []
for no_port in range(1000):
    cap = cv2.VideoCapture(no_port)
    if not cap.isOpened(): continue
    ret, frame = cap.read()
    if ret:
        ports_availables.append(no_port)

print("Ports available: ", ports_availables)

List available resolutions

One way to do it is to manually test every possible resolution:

import cv2

# Data got from https://en.wikipedia.org/wiki/List_of_common_resolutions
RESOLUTIONS_LIST = [
    (16, 16), (42, 11), (32, 32), (40, 30), (42, 32), (48, 32), (60, 40),
    (84, 48), (64, 64), (72, 64), (128, 36), (75, 64), (150, 40), (96, 64),
    (96, 64), (128, 48), (96, 65), (102, 64), (101, 80), (96, 96), (240, 64),
    (160, 102), (128, 128), (160, 120), (160, 144), (144, 168), (160, 152),
    (160, 160), (140, 192), (160, 200), (224, 144), (208, 176), (240, 160),
    (220, 176), (160, 256), (208, 208), (256, 192), (280, 192), (256, 212),
    (432, 128), (256, 224), (240, 240), (256, 240), (320, 192), (320, 192),
    (320, 200), (256, 256), (256, 256), (320, 208), (320, 224), (320, 240),
    (320, 256), (384, 224), (368, 240), (376, 240), (272, 340), (400, 240),
    (512, 192), (448, 224), (320, 320), (432, 240), (560, 192), (400, 270),
    (512, 212), (384, 288), (480, 234), (400, 300), (480, 250), (312, 390),
    (512, 240), (320, 400), (640, 200), (480, 272), (512, 256), (512, 256),
    (416, 352), (480, 320), (640, 240), (640, 240), (640, 256), (512, 342),
    (368, 480), (496, 384), (800, 240), (512, 384), (640, 320), (640, 350),
    (640, 360), (480, 500), (512, 480), (720, 348), (720, 350), (640, 400),
    (720, 364), (800, 352), (600, 480), (640, 480), (640, 512), (768, 480),
    (800, 480), (848, 480), (854, 480), (800, 600), (960, 540), (832, 624),
    (960, 544), (1024, 576), (960, 640), (1024, 600), (1024, 640), (960, 720),
    (1136, 640), (1138, 640), (1024, 768), (1024, 800), (1152, 720), (1152, 768),
    (1280, 720), (1120, 832), (1280, 768), (1152, 864), (1334, 750), (1280, 800),
    (1152, 900), (1024, 1024), (1366, 768), (1280, 854), (1280, 960), (1600, 768),
    (1080, 1200), (1440, 900), (1440, 900), (1280, 1024), (1440, 960), (1600, 900),
    (1400, 1050), (1440, 1024), (1440, 1080), (1600, 1024), (1680, 1050),
    (1776, 1000), (1600, 1200), (1600, 1280), (1920, 1080), (1440, 1440),
    (2048, 1080), (1920, 1200), (2048, 1152), (1792, 1344), (1920, 1280),
    (2280, 1080), (2340, 1080), (1856, 1392), (2400, 1080), (1800, 1440),
    (2880, 900), (2160, 1200), (2048, 1280), (1920, 1400), (2520, 1080),
    (2436, 1125), (2538, 1080), (1920, 1440), (2560, 1080), (2160, 1440),
    (2048, 1536), (2304, 1440), (2256, 1504), (2560, 1440), (2304, 1728),
    (2560, 1600), (2880, 1440), (2960, 1440), (2560, 1700), (2560, 1800),
    (2880, 1620), (2560, 1920), (3440, 1440), (2736, 1824), (2880, 1800),
    (2560, 2048), (2732, 2048), (3200, 1800), (2800, 2100), (3072, 1920),
    (3000, 2000), (3840, 1600), (3200, 2048), (3240, 2160), (5120, 1440),
    (3200, 2400), (3840, 2160), (4096, 2160), (3840, 2400), (4096, 2304),
    (5120, 2160), (4480, 2520), (4096, 3072), (4500, 3000), (5120, 2880),
    (5120, 3200), (5120, 4096), (6016, 3384), (6400, 4096), (6400, 4800),
    (6480, 3240), (7680, 4320), (7680, 4800), (8192, 4320), (8192, 4608),
    (10240, 4320), (8192, 8192), (15360, 8640)
]

cap = cv2.VideoCapture(0)
resolutions_available = set()
for width, height in RESOLUTIONS_LIST:
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
    width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
    height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
    resolutions_available.add((int(width), int(height)))

print(resolutions_available)

Capture video with a fixed framerate

There is no easy and reliable way to set the framerate of the input video capture as it depends on:

  • Your camera’s capture capabilities

  • Your computer’s system resources

  • Whether the current capture backend you’re using supports changing frame rates

See https://stackoverflow.com/questions/52068277/change-frame-rate-in-opencv-3-4-2 and https://stackoverflow.com/questions/12652401/how-to-set-framerate-with-opencv-camera-capture for more info.

The best easy solution is to use a method as below:

import cv2
import time

# Capture video from webcam
cap = cv2.VideoCapture(0)

FPS = 15

time_prev = time.perf_counter()
while(True):
    # Capture frame
    time_elapsed = time.perf_counter() - time_prev
    ret, frame = cap.read()

    if time_elapsed > 1./FPS:
        time_prev = time.perf_counter()
        # Process frame
        # ...
        cv2.imshow("Webcam Capture", frame)
    # Break the loop when pressing "x" key
    if cv2.waitKey(1) &0XFF == ord('x'):
        break

cap.release()
cv2.destroyAllWindows()

Screen Capture

If you want to capture your screen, you can use the (PIL.ImageGrab.grab) method, however it doesn’t work on Linux systems (at least for me). Alternatively, you can use the package mss (conda install -c conda-forge python-mss).

More info here: https://stackoverflow.com/questions/24129253/screen-capture-with-opencv-and-python-2-7

import cv2
import numpy as np
from mss import mss

mon = {'top': 0, 'left': 0, 'width': 1920, 'height': 1200}
with mss() as sct:
    while True:
        img = sct.grab(mon)
        cv2.imshow('Screen Capture', np.array(img))
        if cv2.waitKey(25) & 0xFF == ord('q'):
            break
    cv2.destroyAllWindows()

Sources: