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