I'm using python and OpenCV to acquire video from the webcam. So as to record the video, I need the FPS information.
From get
property of cv.VideoCapture
I get 30fps:
fps = cap.get(cv.CAP_PROP_FPS)
However, when I build the thread that reads the subsequent frames, the actual framerate seems to be much lower (~12):
def run(self) -> None:
log(f'Started frame grabber with FPS = {self.fps}')
while self.keep_grabbing:
_now = time.perf_counter()
# frame = self.cap.grab() # SAME RESULT AS WITH read()
ret, frame = self.cap.read()
now = time.perf_counter()
log(f'Elapsed Time: {now - _now}')
The result is an average 0.083s elapsed (about 12fps) I can't understand if I'm getting a slow software (but I cannot figure out what to change), or if the get property is returning a wrong FPS. Any suggestion?
The problem was the ApiPreference
with which the camera was opened. By default the cv.CAP_ANY
was used that implied the behavior described by the question. It seems that the auto-detection of the API does not work effectively
In particular, for the PC's webcam under Ubuntu 20.04, the parameter cv.CAP_V4L
makes the camera work with an effective FPS of 29.8, very near to the theoretical one (30).
The code becomes:
import cv2 as cv
import time
# Here the ApiPreference must be chosen carefully
cap = cv.VideoCapture(0, cv.CAP_V4L)
if not cap.isOpened():
exit('Camera not opened')
while True:
_now = time.perf_counter()
ret, frame = cap.read()
now = time.perf_counter()
print(f'Elapsed Time: {now - _now}')
if not ret:
exit('Frame not grabbed')