Search code examples
pythonopencvcameraframe-rate

Python/OpenCV - Wrong actual camera FPS or too slow routine


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?


Solution

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