Example #1
0
class VideoCamera(object):
    def __init__(
    self,
    src=0,
    flip = False, usePiCamera = True,
    fps = 20.0,
    resolution = (640,480),
    record = False, record_duration = None, record_timestamp = True,
    record_name = None
    ):

        if resolution is None:
            resolution = (320, 240)
        self.vs = VideoStream(src=src, usePiCamera = usePiCamera, resolution = resolution).start()
        #if usePiCamera is False:
        #    # we need to change things here because it will ignore resolution if not using the piCam
        #    # https://github.com/PyImageSearch/imutils/issues/55
        #    # this is not currently working!!!!
        #    self.vs.stream.set(3, resolution[0])
        #    self.vs.stream.set(4, resolution[1])
        self.flip = flip
        # Record settings ###
        # no recording set at init
        self.rec_set = False
        self.record = record
        # trigger record
        self.trigger_record = record
        self.resolution = resolution
        self.fps = fps
        # we might be in trouble if we switch from color to grayscale
        self.isColor = self.is_color()
        self.record_start = None
        self.record_name = record_name
        if (record_duration is not None):
            session_time = datetime.datetime.strptime(record_duration, '%H:%M:%S')
            # Transform the time into number of seconds
            seconds = (session_time.hour * 60 + session_time.minute) * 60 + session_time.second
            self.record_duration = seconds
        self.record_timestamp = record_timestamp
        # this is so that all timestamped things have a consistent format
        self.timestamp_format = '%Y-%m-%dT%H-%M-%S'
        if (self.record == True):
            # we will use timestamps to prevent overwriting
            if self.record_name is None:
                self.name = datetime.datetime.now().strftime(self.timestamp_format) + "_output"
            else:
                self.name = f"{datetime.datetime.now().strftime(self.timestamp_format)}_{str(self.record_name)}_output"
            # start video_writer
            self.video_writer = VideoWriter(filename=self.name, fps=self.fps, resolution = self.resolution)
        time.sleep(2.0)



    def __del__(self):
        self.vs.stop()
        self.vs.stream.release()
        if (self.record):
            self.video_writer.stop()

    def is_color(self):
        frame = self.vs.read()
        if (len(frame.shape) == 3):
            return True
        else:
            return False


    def flip_if_needed(self, frame):
        if self.flip:
            return np.flip(frame, 0)
        return frame

    def read(self):
        # this is the read function we want to do processing
        frame = self.flip_if_needed(self.vs.read())
        timestamp = datetime.datetime.now()
        if (self.trigger_record):
            # check whether the video size is ok or we need to chunk
            self.check_video_filesize()
            if (self.record_timestamp):
                cv2.putText(frame, str(timestamp),
                    (10, 50), 
                    cv2.FONT_HERSHEY_SIMPLEX, 
                    1,
                    (255,255,255),
                    1)
            # let's only call it if the framerate is ok
            if (self.check_framerate(timestamp)):
                self.video_writer.put_to_q(frame, timestamp)
            # self.record(frame)
        return frame

    # This function handles the posting of .jpg through ip stream
    def get_frame(self, label_time, camera_stamp = None):
        # This function ends up converting to jpg and timestamping
        # intended for streaming 
        upload_frame = self.flip_if_needed(self.vs.read())
        if (label_time):
            cv2.putText(upload_frame, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), 
                (10, 50), 
                cv2.FONT_HERSHEY_SIMPLEX, 
                1,
                (255,255,255),
                1)
        if (camera_stamp is not None):
            cv2.putText(upload_frame, str(camera_stamp), 
                (10, self.resolution[1] - 50), 
                cv2.FONT_HERSHEY_SIMPLEX, 
                1,
                (255,255,255),
                1)

        ret, jpeg = cv2.imencode('.jpg', upload_frame)
        return jpeg.tobytes()

    # We can use this function if we had a classifier that was well suited
    # It might need computation power to do this in real time
    def get_object(self, classifier):
        found_objects = False
        frame = self.flip_if_needed(self.vs.read()).copy() 
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        objects = classifier.detectMultiScale(
            gray,
            scaleFactor=1.1,
            minNeighbors=5,
            minSize=(30, 30),
            flags=cv2.CASCADE_SCALE_IMAGE
        )

        if len(objects) > 0:
            found_objects = True

        # Draw a rectangle around the objects
        for (x, y, w, h) in objects:
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

        ret, jpeg = cv2.imencode('.jpg', frame)
        return (jpeg.tobytes(), found_objects)

    # The function below has problems with frame rate not being constant
    # We account for frame rate by assuming constant frame rate but that fails in real life
    def record(self, frame):
        """
        Opencv VideoWriter
        https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_gui/py_video_display/py_video_display.html
        This time we create a VideoWriter object. 
        We should specify the output file name (eg: output.avi).
        Then we should specify the FourCC code (details in next paragraph).
        Then number of frames per second (fps) and frame size should be passed.
        And last one is isColor flag. If it is True, encoder expect color frame,
        otherwise it works with grayscale frame.

        Example comes from here
        https://stackoverflow.com/questions/30509573/writing-an-mp4-video-using-python-opencv
        """
        if (self.rec_set == False):
            self.fourcc = cv2.VideoWriter_fourcc(*'XVID')
            self.recorder = cv2.VideoWriter(self.name, self.fourcc, self.fps, self.resolution, self.isColor)
            self.rec_set = True
            self.prev_frame = time.time()
            self.record_start = self.prev_frame
        else:
            # account for fps
            # otherwise, we would need to account for this via waitKey(int(1000/fps)) 
            current_frame = time.time()
            if (current_frame - self.prev_frame > 1/self.fps):
                self.prev_frame = current_frame

            if (self.prev_frame - self.record_start > self.record_duration):
                print(self.prev_frame)
                print(self.record_start)
                print(self.record_duration)
                # stop the recording (not the camera)
                self.trigger_record = False

    def check_framerate(self, timestamp):
        if (self.rec_set == False):
            self.rec_set = True
            self.prev_frame = timestamp
            self.record_start = self.prev_frame
            return True
        else:
            # account for fps
            # otherwise, we would need to account for this via waitKey(int(1000/fps)) 
            delta_time = (timestamp - self.prev_frame).total_seconds() 
            if (delta_time > 1/self.fps):
                self.prev_frame = timestamp
                return True

            current_duration = (self.prev_frame - self.record_start).total_seconds()

            if (current_duration > self.record_duration):
                print(self.prev_frame)
                print(self.record_start)
                print(self.record_duration)
                # stop the recording (not the camera)
                self.video_writer.stop()
                # stop triggering record in the future
                self.trigger_record = False
        # if we got up to here and no conditions were met
        return False

    def check_video_filesize(self):
        #TODO: Potential problem harcoded extension, it's also harcoded on videowriter 
        if os.path.exists(self.name + ".avi"):
            current_size = os.stat(self.name + ".avi").st_size
            # size will be in bytes, let's have a limit of 100 Mb
            if (current_size > 100 * 1024 * 1024):
                # stop the video writer
                self.video_writer.stop()
                print("Video truncated...initializing new clip")
                if self.record_name is None:
                   self.name = datetime.datetime.now().strftime(self.timestamp_format) + "_output"
                else:
                    self.name = f"{datetime.datetime.now().strftime(self.timestamp_format)}_{str(self.record_name)}_output"
                # start the writer again
                self.video_writer = VideoWriter(filename=self.name, fps=self.fps, resolution = self.resolution)
Example #2
0
                                  30, (realsensecam().W, realsensecam().H),
                                  threaded=False)

    breakpoints = args.b__breakpoints or []
    while (True):
        img = controller().next_frame()
        if img is None:
            print("Controller reports end of capture. Terminating.")
            break
        cv2.imshow('DynamicUIs', img)
        k = cv2.waitKey(1)
        if ord('q') == k:
            break
        else:
            controller().on_key(k)
        if args.video_output is not None:
            videowriter.process_frame(realsensecam().bgr,
                                      realsensecam().depth_processed)
        if controller().frame in breakpoints:
            print("Paused at breakpoint", controller().frame)
            print("Press Space to advance by a single frame")
            k = cv2.waitKey()
            if k == ord(' '):
                breakpoints.append(controller().frame + 1)
    realsensecam().stop()  # Stop camera
    if args.video_output is not None:
        videowriter.stop()

    if logger is not None:
        logger.dump(args.logfile)