Loading openflexure_microscope/camera/base.py +9 −3 Original line number Diff line number Diff line Loading @@ -96,6 +96,9 @@ class BaseCamera(object): self.last_access = 0 #: time: Time of last client access to the camera self.event = CameraEvent() self.stream_timeout = 20 #: int: Number of inactive seconds before timing out the stream self.stream_timeout_enabled = True #: bool: Enable or disable timing out the stream self.state = {} #: dict: Dictionary for capture state self._config = {} #: dict: Dictionary of base camera settings self.paths = { Loading Loading @@ -257,9 +260,12 @@ class BaseCamera(object): self.event.set() # send signal to clients time.sleep(0) # if there hasn't been any clients asking for frames in # the last 10 seconds then stop the thread if time.time() - self.last_access > 20: # Handle timeout if ( self.stream_timeout_enabled and # If using timeout (time.time() - self.last_access > self.stream_timeout) and # And timeout time not self.state['preview_active'] # And GPU preview is not active ): self.frames_iterator.close() break Loading openflexure_microscope/camera/pi.py +16 −25 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ Camera capture resolution set to video_resolution in frames() Video port uses that resolution for everything. If a different resolution is specified for video capture, this is handled by the resizer. Still capture (if use_video_port == False) uses pause_stream_for_capture Still capture (if use_video_port == False) uses pause_stream to temporarily increase the capture resolution. """ Loading Loading @@ -208,7 +208,7 @@ class StreamingCamera(BaseCamera): # Pause stream while changing settings if self.state['stream_active']: # If stream is active logging.info("Pausing stream to update config.") self.pause_stream_for_capture() # Pause stream self.pause_stream() # Pause stream paused_stream = True # Remember to unpause stream when done # PiCamera parameters (applied directly to PiCamera object) Loading Loading @@ -237,7 +237,7 @@ class StreamingCamera(BaseCamera): # If stream was paused to update config, unpause if paused_stream: logging.info("Resuming stream.") self.resume_stream_for_capture() self.resume_stream() else: raise Exception( Loading Loading @@ -355,7 +355,7 @@ class StreamingCamera(BaseCamera): # Update state dictionary self.state['record_active'] = False def pause_stream_for_capture( def pause_stream( self, splitter_port: int=1, resolution: Tuple[int, int]=None) -> None: Loading @@ -377,7 +377,7 @@ class StreamingCamera(BaseCamera): # Increase the resolution for taking an image self.camera.resolution = resolution def resume_stream_for_capture( def resume_stream( self, splitter_port: int=1, resolution: Tuple[int, int]=None) -> None: Loading @@ -388,7 +388,7 @@ class StreamingCamera(BaseCamera): splitter_port (int): Splitter port to start recording on resolution ((int, int)): Resolution to set the camera to, before starting recording. """ logging.debug("Unpausing stream") logging.debug("Resuming stream") if not resolution: resolution = self.config['video_resolution'] Loading Loading @@ -453,7 +453,7 @@ class StreamingCamera(BaseCamera): if not use_video_port: # Pause video splitter port 1 self.pause_stream_for_capture() self.pause_stream() self.camera.capture( target, Loading @@ -463,7 +463,7 @@ class StreamingCamera(BaseCamera): bayer=True) # Resume video splitter port 1 self.resume_stream_for_capture() self.resume_stream() else: self.camera.capture( Loading Loading @@ -498,7 +498,7 @@ class StreamingCamera(BaseCamera): size = resolution if not use_video_port: self.pause_stream_for_capture(resolution=resolution) self.pause_stream(resolution=resolution) logging.debug("Creating PiYUVArray") with picamera.array.PiYUVArray(self.camera, size=size) as output: Loading @@ -512,7 +512,7 @@ class StreamingCamera(BaseCamera): use_video_port=use_video_port) if not use_video_port: self.resume_stream_for_capture() self.resume_stream() if rgb: logging.debug("Converting to RGB") Loading @@ -523,19 +523,13 @@ class StreamingCamera(BaseCamera): def array( self, use_video_port: bool=True, resize: Tuple[int, int]=None, stop_worker: bool=True) -> np.ndarray: resize: Tuple[int, int]=None) -> np.ndarray: """Capture an uncompressed still RGB image to a Numpy array. Args: use_video_port (bool): Capture from the video port used for streaming. Lower resolution, faster. resize ((int, int)): Resize the captured image. stop_worker (bool): Auto-stop worker, to avoid GPU memory issues """ restart_worker = False if stop_worker is True and self.stop is False: self.stop_worker() restart_worker = True if use_video_port: resolution = self.config['video_resolution'] Loading @@ -547,8 +541,8 @@ class StreamingCamera(BaseCamera): else: size = resolution if not use_video_port: self.pause_stream_for_capture(resolution=resolution) # Always pause stream, to prevent resizer memory issues self.pause_stream(resolution=resolution) logging.debug("Creating PiRGBArray") with picamera.array.PiRGBArray(self.camera, size=size) as output: Loading @@ -561,11 +555,8 @@ class StreamingCamera(BaseCamera): format='rgb', use_video_port=use_video_port) if not use_video_port: self.resume_stream_for_capture() if restart_worker: self.start_worker() # Resume stream self.resume_stream() return output.array Loading openflexure_microscope/utilities/recalibrate.py +5 −1 Original line number Diff line number Diff line Loading @@ -104,7 +104,6 @@ def generate_lens_shading_table_closed_loop(output_fname="shadingtable.npy", # Open the microscope and start with flat (i.e. no) lens shading correction. cam.start_preview() logging.info("Stopping worker thread during calibration, to avoid GPU memory issues") cam.stop_worker() def get_rgb_image(): # shorthand for taking an RGB image return cam.array(use_video_port=True, resize=(max_res[0]//2, max_res[1]//2)) Loading @@ -125,8 +124,11 @@ def generate_lens_shading_table_closed_loop(output_fname="shadingtable.npy", rgb_image = np.mean(images, axis=0, dtype=np.float) incremental_gains = lens_shading_correction_from_rgb(rgb_image, 64//2) gains *= incremental_gains # Apply this change (actually apply a bit less than the change) cam.pause_stream() cam.camera.lens_shading_table = gains_to_lst(gains*32) cam.resume_stream() time.sleep(2) # Fix the AWB gains so the image is neutral Loading Loading @@ -158,6 +160,8 @@ def generate_lens_shading_table_closed_loop(output_fname="shadingtable.npy", logging.debug("Merging config...") config.merge_config(settings, safe=True, backup=True) #cam.resume_stream_for_capture() if __name__ == '__main__': generate_lens_shading_table_closed_loop() No newline at end of file Loading
openflexure_microscope/camera/base.py +9 −3 Original line number Diff line number Diff line Loading @@ -96,6 +96,9 @@ class BaseCamera(object): self.last_access = 0 #: time: Time of last client access to the camera self.event = CameraEvent() self.stream_timeout = 20 #: int: Number of inactive seconds before timing out the stream self.stream_timeout_enabled = True #: bool: Enable or disable timing out the stream self.state = {} #: dict: Dictionary for capture state self._config = {} #: dict: Dictionary of base camera settings self.paths = { Loading Loading @@ -257,9 +260,12 @@ class BaseCamera(object): self.event.set() # send signal to clients time.sleep(0) # if there hasn't been any clients asking for frames in # the last 10 seconds then stop the thread if time.time() - self.last_access > 20: # Handle timeout if ( self.stream_timeout_enabled and # If using timeout (time.time() - self.last_access > self.stream_timeout) and # And timeout time not self.state['preview_active'] # And GPU preview is not active ): self.frames_iterator.close() break Loading
openflexure_microscope/camera/pi.py +16 −25 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ Camera capture resolution set to video_resolution in frames() Video port uses that resolution for everything. If a different resolution is specified for video capture, this is handled by the resizer. Still capture (if use_video_port == False) uses pause_stream_for_capture Still capture (if use_video_port == False) uses pause_stream to temporarily increase the capture resolution. """ Loading Loading @@ -208,7 +208,7 @@ class StreamingCamera(BaseCamera): # Pause stream while changing settings if self.state['stream_active']: # If stream is active logging.info("Pausing stream to update config.") self.pause_stream_for_capture() # Pause stream self.pause_stream() # Pause stream paused_stream = True # Remember to unpause stream when done # PiCamera parameters (applied directly to PiCamera object) Loading Loading @@ -237,7 +237,7 @@ class StreamingCamera(BaseCamera): # If stream was paused to update config, unpause if paused_stream: logging.info("Resuming stream.") self.resume_stream_for_capture() self.resume_stream() else: raise Exception( Loading Loading @@ -355,7 +355,7 @@ class StreamingCamera(BaseCamera): # Update state dictionary self.state['record_active'] = False def pause_stream_for_capture( def pause_stream( self, splitter_port: int=1, resolution: Tuple[int, int]=None) -> None: Loading @@ -377,7 +377,7 @@ class StreamingCamera(BaseCamera): # Increase the resolution for taking an image self.camera.resolution = resolution def resume_stream_for_capture( def resume_stream( self, splitter_port: int=1, resolution: Tuple[int, int]=None) -> None: Loading @@ -388,7 +388,7 @@ class StreamingCamera(BaseCamera): splitter_port (int): Splitter port to start recording on resolution ((int, int)): Resolution to set the camera to, before starting recording. """ logging.debug("Unpausing stream") logging.debug("Resuming stream") if not resolution: resolution = self.config['video_resolution'] Loading Loading @@ -453,7 +453,7 @@ class StreamingCamera(BaseCamera): if not use_video_port: # Pause video splitter port 1 self.pause_stream_for_capture() self.pause_stream() self.camera.capture( target, Loading @@ -463,7 +463,7 @@ class StreamingCamera(BaseCamera): bayer=True) # Resume video splitter port 1 self.resume_stream_for_capture() self.resume_stream() else: self.camera.capture( Loading Loading @@ -498,7 +498,7 @@ class StreamingCamera(BaseCamera): size = resolution if not use_video_port: self.pause_stream_for_capture(resolution=resolution) self.pause_stream(resolution=resolution) logging.debug("Creating PiYUVArray") with picamera.array.PiYUVArray(self.camera, size=size) as output: Loading @@ -512,7 +512,7 @@ class StreamingCamera(BaseCamera): use_video_port=use_video_port) if not use_video_port: self.resume_stream_for_capture() self.resume_stream() if rgb: logging.debug("Converting to RGB") Loading @@ -523,19 +523,13 @@ class StreamingCamera(BaseCamera): def array( self, use_video_port: bool=True, resize: Tuple[int, int]=None, stop_worker: bool=True) -> np.ndarray: resize: Tuple[int, int]=None) -> np.ndarray: """Capture an uncompressed still RGB image to a Numpy array. Args: use_video_port (bool): Capture from the video port used for streaming. Lower resolution, faster. resize ((int, int)): Resize the captured image. stop_worker (bool): Auto-stop worker, to avoid GPU memory issues """ restart_worker = False if stop_worker is True and self.stop is False: self.stop_worker() restart_worker = True if use_video_port: resolution = self.config['video_resolution'] Loading @@ -547,8 +541,8 @@ class StreamingCamera(BaseCamera): else: size = resolution if not use_video_port: self.pause_stream_for_capture(resolution=resolution) # Always pause stream, to prevent resizer memory issues self.pause_stream(resolution=resolution) logging.debug("Creating PiRGBArray") with picamera.array.PiRGBArray(self.camera, size=size) as output: Loading @@ -561,11 +555,8 @@ class StreamingCamera(BaseCamera): format='rgb', use_video_port=use_video_port) if not use_video_port: self.resume_stream_for_capture() if restart_worker: self.start_worker() # Resume stream self.resume_stream() return output.array Loading
openflexure_microscope/utilities/recalibrate.py +5 −1 Original line number Diff line number Diff line Loading @@ -104,7 +104,6 @@ def generate_lens_shading_table_closed_loop(output_fname="shadingtable.npy", # Open the microscope and start with flat (i.e. no) lens shading correction. cam.start_preview() logging.info("Stopping worker thread during calibration, to avoid GPU memory issues") cam.stop_worker() def get_rgb_image(): # shorthand for taking an RGB image return cam.array(use_video_port=True, resize=(max_res[0]//2, max_res[1]//2)) Loading @@ -125,8 +124,11 @@ def generate_lens_shading_table_closed_loop(output_fname="shadingtable.npy", rgb_image = np.mean(images, axis=0, dtype=np.float) incremental_gains = lens_shading_correction_from_rgb(rgb_image, 64//2) gains *= incremental_gains # Apply this change (actually apply a bit less than the change) cam.pause_stream() cam.camera.lens_shading_table = gains_to_lst(gains*32) cam.resume_stream() time.sleep(2) # Fix the AWB gains so the image is neutral Loading Loading @@ -158,6 +160,8 @@ def generate_lens_shading_table_closed_loop(output_fname="shadingtable.npy", logging.debug("Merging config...") config.merge_config(settings, safe=True, backup=True) #cam.resume_stream_for_capture() if __name__ == '__main__': generate_lens_shading_table_closed_loop() No newline at end of file