# Top level class for a video capture providing simplified API's for common # functions # Import required modules import configparser import cv2 import os import sys """ Class to provide boilerplate code to build a video recorder with the correct settings from the config file. The internal recorder can be accessed with 'video_capture.internal' """ class VideoCapture: """ Creates a new VideoCapture instance depending on the settings in the provided config file. Config can either be a string to the path, or a pre-setup configparser. """ def __init__(self, config): if isinstance(config, str): self.config = configparser.ConfigParser() self.config.read(config) else: self.config = config # Check device path if not os.path.exists(config.get("video", "device_path")): print("Camera path is not configured correctly, " + "please edit the 'device_path' config value.") sys.exit(1) # Create reader self.internal = None # The internal video recorder self.fw = None # The frame width self.fh = None # The frame height self._create_reader() # Request a frame to wake the camera up self.internal.grab() """ Frees resources when destroyed """ def __del__(self): if self is not None: self.internal.release() """ Reads a frame, returns the frame and an attempted grayscale conversion of the frame in a tuple: (frame, grayscale_frame) If the grayscale conversion fails, both items in the tuple are identical. """ def read_frame(self): # Grab a single frame of video # Don't remove ret, it doesn't work without it ret, frame = self.internal.read() if not ret: print("Failed to read camera specified in your 'device_path', " + "aborting") sys.exit(1) try: # Convert from color to grayscale # First processing of frame, so frame errors show up here gsframe = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) except RuntimeError: gsframe = frame except cv2.error: print("\nAn error occurred in OpenCV\n") raise return frame, gsframe """ Sets up the video reader instance """ def _create_reader(self): if self.config.get("video", "recording_plugin") == "ffmpeg": # Set the capture source for ffmpeg from recorders.ffmpeg_reader import ffmpeg_reader self.internal = ffmpeg_reader( self.config.get("video", "device_path"), self.config.get("video", "device_format") ) elif self.config.get("video", "recording_plugin") == "pyv4l2": # Set the capture source for pyv4l2 from recorders.pyv4l2_reader import pyv4l2_reader self.internal = pyv4l2_reader( self.config.get("video", "device_path"), self.config.get("video", "device_format") ) else: # Start video capture on the IR camera through OpenCV self.internal = cv2.VideoCapture( self.config.get("video", "device_path") ) # Force MJPEG decoding if true if self.config.getboolean("video", "force_mjpeg", fallback=False): # Set a magic number, will enable MJPEG but is badly documentated self.internal.set(cv2.CAP_PROP_FOURCC, 1196444237) # Set the frame width and height if requested self.fw = self.config.getint("video", "frame_width", fallback=-1) self.fh = self.config.getint("video", "frame_height", fallback=-1) if self.fw != -1: self.internal.set(cv2.CAP_PROP_FRAME_WIDTH, self.fw) if self.fh != -1: self.internal.set(cv2.CAP_PROP_FRAME_HEIGHT, self.fh)