pythonopencvcomputer-visioncamerawebcam

OpenCV get framerate and frame timestamp from live webcam stream?


I'm struggling a bit trying to read/set the fps for my webcam and to read the timestamp for specific frames captured from my webcam. Specifically when I try to use vc.get(cv2.CAP_PROP_POS_MSEC), vc.get(cv2.CAP_PROP_FPS), vc.get(cv2.CAP_PROP_FRAME_COUNT) they return respectively -1, 0, -1. Clearly there's something that I'm missing. Can someone help? The code looks like this:

import os
import time

import cv2
import numpy as np
[...]
# Create a new VideoCapture object
vc = cv2.VideoCapture(0, cv2.CAP_DSHOW)
vc.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
vc.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)

# Initialise variables to store current time difference as well as previous time call value
previous = time.time()
delta = 0
n = len(os.listdir("directory"))

# Keep looping
while True:
    timem = vc.get(cv2.CAP_PROP_POS_MSEC)
    fps = vc.get(cv2.CAP_PROP_FPS)
    total_frames = vc.get(cv2.CAP_PROP_FRAME_COUNT)

    print(timem, fps, total_frames)
    # Get the current time, increase delta and update the previous variable
    current = time.time()
    delta += current - previous
    previous = current

    # Check if 3 (or some other value) seconds passed
    if delta > 3:
        # Operations on image
        # Reset the time counter
        delta = 0

        _, img = vc.read()
        [...]
        # press esc to exit
    if cv2.waitKey(20) == 27:
        break

edit: if I remove cv2.CAP_DSHOW, it works, but then I cannot use CAP_PROP_FRAME_WIDTH


Solution

  • Apparently the OpenCV backend for cameras on your operating system (DSHOW) does not keep track of frame timestamps.

    After a read(), just use time.perf_counter() or a sibling function. It'll be close enough, unless you throttle the reading, in which case the frames would be stale.

    You could open an issue on OpenCV's github and request such a feature for DSHOW/MSMF. One would expect such a timestamp to represent the time the frame was taken, not the time it was finally read by the user program.