pythonopencvvideo-streamingvideo-capture

VideoCapture frames images corrupted: shifting one of the channels on random frames


The camera works correctly, when I use the software to verify the camera I see no corrupted frames so I assume that this is issues are coming from OpenCV.

I notice that random frames (one out of 10-20 frames) are corrupted and one of the channels is shifted. Example below.

enter image description here

I am running the camera code as a service that runs in the background so any other application can obtain the latest frame and make use of it without having to run the read frame loop and work with asynchronous code.

import threading
import time
import cv2 as cv
import numpy as np

class CameraCU81():
    def __init__(self, W=1920, H=1080, hz=30):
        self.cap = cv.VideoCapture(0)
        self.last_frame = None
        # if recording mjgp the frames hangs...
        #self.cap.set(cv.CAP_PROP_FOURCC, cv.VideoWriter_fourcc('M', 'J', 'P', 'G'))
        print(str(cv.VideoWriter_fourcc('M', 'J', 'P', 'G')))
        self.cap.set(cv.CAP_PROP_FRAME_WIDTH, W)
        self.cap.set(cv.CAP_PROP_FRAME_HEIGHT, H)
        self.cap.set(cv.CAP_PROP_FPS, hz)
        print('Starting camera 81 fps at: ' +  str(self.cap.get(cv.CAP_PROP_FPS)))
        w = str(self.cap.get(cv.CAP_PROP_FRAME_WIDTH))
        h = str(self.cap.get(cv.CAP_PROP_FRAME_HEIGHT))
        print('Starting camera 81 resolution at: ' + w + ' x ' + h)
        format = str(self.cap.get(cv.CAP_PROP_FOURCC))
        print('Starting camera 81 format: ' + format)

def __capture_frames(self):
    error_f = False
    while True:
        start_time = time.time()
        ret, frame = self.cap.read()
        if not ret:
            timeout_time = (time.time() - start_time)
            print('Frame could not be read ... is camera connected?')
            print(timeout_time)
            error_f = True
        else:
            self.last_frame = frame
            if error_f:
                timeout_time = (time.time() - start_time)
                print(timeout_time)

def get_data(self):
    return self.last_frame

def destroy(self):
    self.cap.release()

def run(self):
    t1 = threading.Thread(target=self.__capture_frames)
    t1.daemon = True
    t1.start()

Solution

  • After some weeks I found out that I was hitting the USB throughput of my raspberry Pi 4. Connecting 2 cameras to USB3.0 was an issue.

    Dropped resolution of one of my cameras and then connected one camera to the USB2.0 bus and the other one to USB3.0 bus.