What causes the measured fps to be different from the expected yet possible fps?

Tags: ,



What causes the measured fps to be different from the expected yet possible fps?

My webcam has 30 fps (maximum) and the measured fps is only about 20 fps.

The logic behind my code:

  • One iteration shows one frame.
  • The total time for one iteration is the sum of tc, td and d.
  • The reciprocal of the sum is the measured fps.
  • delay passed to waitKey is calculated by subtracting tc+td from the reciprocal of the expected FPS. Or, delay=(1/FPS - tc - td)*1000 (milliseconds).

enter image description here

import cv2
import time

FPS = 30    # expected fps
fps = FPS   # measured fps
tc = 0.000  # measured time to capture frame
tp = 0.000  # measured time to process frame
d = 0.001   # measured time to wait for pressing ESC key

cap = cv2.VideoCapture(0)
while True:
    # labeling the results of the previous round
    lblTC = f" tc: {int(1000 * tc):4}"
    lblTP = f" tp: {int(1000 * tp):4}"
    lblD = f"  d: {int(1000 * d):4}"
    lblFPS = f"fps: {fps}"

    # measuring time to capture frame
    begin = time.time()
    _, frame = cap.read()
    end = time.time()
    tc = end - begin

    # measuring time to process frame
    begin = time.time()
    frame = cv2.flip(frame, 1)
    frame = cv2.putText(frame, lblTC, (10, 40),
                        cv2.FONT_HERSHEY_PLAIN, 2.5, (0, 128, 255), 2)
    frame = cv2.putText(frame, lblTP, (10, 80),
                        cv2.FONT_HERSHEY_PLAIN, 2.5, (0, 128, 255), 2)
    frame = cv2.putText(frame, lblD, (10, 120),
                        cv2.FONT_HERSHEY_PLAIN, 2.5, (0, 128, 255), 2)
    frame = cv2.putText(frame, lblFPS, (10, 160),
                        cv2.FONT_HERSHEY_PLAIN, 2.5, (0, 128, 255), 2)
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    cv2.namedWindow("cam", cv2.WINDOW_NORMAL)
    cv2.imshow("cam", frame)
    end = time.time()
    tp = end - begin

    delay = int((1 / FPS - tc - tp) * 1000)
    if delay < 1:
        delay = 1  # set delay to 1 to prevent forever waiting
    # measuring time to wait for pressing ESC key
    begin = time.time()
    if cv2.waitKey(delay) == 27:
        break
    end = time.time()
    d = end - begin

    # calculating the measured fps
    fps = int(1 / (tc + tp + d))

Answer

According to the OpenCV Documentation:

The function waitKey waits for a key event infinitely (when delay <= 0 ) or for delay milliseconds, when it is positive. Since the OS has a minimum time between switching threads, the function will NOT wait exactly delay ms, it will wait AT LEAST delay ms, depending on what else is running on your computer at that time. It returns the code of the pressed key or -1 if no key was pressed before the specified time had elapsed.

Therefore, in my opinion (correct if I am wrong), always use waitKey(1) when streaming from a webcam to

  • let the webcam itself adjust its possible maximum fps
  • reduce lagging because of unpredictable waitKey delay


Source: stackoverflow