diff --git a/imutils/video/__init__.py b/imutils/video/__init__.py index 4c0bd33..181630f 100644 --- a/imutils/video/__init__.py +++ b/imutils/video/__init__.py @@ -2,5 +2,6 @@ from .count_frames import count_frames from .fps import FPS from .videostream import VideoStream +from .pivideostream import PiVideoStream from .webcamvideostream import WebcamVideoStream from .filevideostream import FileVideoStream \ No newline at end of file diff --git a/imutils/video/pivideostream.py b/imutils/video/pivideostream.py index c7c5931..b6c3958 100644 --- a/imutils/video/pivideostream.py +++ b/imutils/video/pivideostream.py @@ -2,45 +2,58 @@ from picamera.array import PiRGBArray from picamera import PiCamera from threading import Thread +import logging import cv2 class PiVideoStream: - def __init__(self, resolution=(320, 240), framerate=32): + def __init__(self, resolution=(320, 240), framerate=30, sensor_mode = 0, logging = False, **options): # initialize the camera and stream self.camera = PiCamera() self.camera.resolution = resolution self.camera.framerate = framerate + self.camera.sensor_mode = sensor_mode + for key, value in options.items(): + setattr(self.camera, key, value) self.rawCapture = PiRGBArray(self.camera, size=resolution) - self.stream = self.camera.capture_continuous(self.rawCapture, - format="bgr", use_video_port=True) + self.stream = self.camera.capture_continuous(self.rawCapture,format="bgr", use_video_port=True) + + #thread intialization + self.thread = None + + #enable logging + self.logging = logging - # initialize the frame and the variable used to indicate - # if the thread should be stopped - self.frame = None self.stopped = False + def start(self): # start the thread to read frames from the video stream - t = Thread(target=self.update, args=()) - t.daemon = True - t.start() + self.thread = Thread(target=self.update, args=()) + self.thread.daemon = True + self.thread.start() return self def update(self): # keep looping infinitely until the thread is stopped - for f in self.stream: + try: + for stream in self.stream: # grab the frame from the stream and clear the stream in # preparation for the next frame - self.frame = f.array - self.rawCapture.truncate(0) - - # if the thread indicator variable is set, stop the thread - # and resource camera resources - if self.stopped: - self.stream.close() - self.rawCapture.close() - self.camera.close() - return + if stream is None: + self.stopped =True + if self.stopped: + break + self.frame = stream.array + self.rawCapture.seek(0) + self.rawCapture.truncate() + except Exception as e: + if self.logging: + logging.error(traceback.format_exc()) + pass + # release resource camera resources + self.stream.close() + self.rawCapture.close() + self.camera.close() def read(self): # return the frame most recently read @@ -49,3 +62,8 @@ def read(self): def stop(self): # indicate that the thread should be stopped self.stopped = True + # wait until stream resources are released (producer thread might be still grabbing frame) + if self.thread is not None: + self.thread.join() + #properly handle thread exit + diff --git a/imutils/video/webcamvideostream.py b/imutils/video/webcamvideostream.py index dbe8751..18fb6e5 100644 --- a/imutils/video/webcamvideostream.py +++ b/imutils/video/webcamvideostream.py @@ -12,15 +12,18 @@ def __init__(self, src=0, name="WebcamVideoStream"): # initialize the thread name self.name = name + #thread intialization + self.thread=None + # initialize the variable used to indicate if the thread should # be stopped self.stopped = False def start(self): # start the thread to read frames from the video stream - t = Thread(target=self.update, name=self.name, args=()) - t.daemon = True - t.start() + self.thread = Thread(target=self.update, name=self.name, args=()) + self.thread.daemon = True + self.thread.start() return self def update(self): @@ -28,11 +31,20 @@ def update(self): while True: # if the thread indicator variable is set, stop the thread if self.stopped: - return + #based on my previous PR + break # otherwise, read the next frame from the stream (self.grabbed, self.frame) = self.stream.read() + #check for valid frames + if not self.grabbed: + #no frames recieved, then safely exit + self.stopped = True + + #release resources + self.stream.release() + def read(self): # return the frame most recently read return self.frame @@ -40,3 +52,7 @@ def read(self): def stop(self): # indicate that the thread should be stopped self.stopped = True + # wait until stream resources are released (producer thread might be still grabbing frame) + if self.thread is not None: + self.thread.join() + #properly handle thread exit