def _get_image(self, value, raw=False): if value is None: return None width, height = self.get_raw_geometry() size = width * height if value.size != size: if value.size < size: _logger.warning( "Image array too small: %d - shape: %dx%d [%s]." % (value.size, width, height, self.camera_config.get_source())) return None else: value = value[:(size)] # Shape image value = value.reshape((height, width)) # Return raw image without any corrections if raw: return value return transform_image(value, self.camera_config)
def _get_image(self, value, raw=False): if value is None: return None width, height = self.get_raw_geometry() size = width * height if value.size != size: if value.size < size: _logger.warning( "Image array too small: %d - shape: %dx%d [%s]." % (value.size, width, height, self.prefix)) return None else: value = value[:(size)] # Shape images value = value.reshape((height, width)) if value.dtype == "uint8": value = value.astype("int16") elif value.dtype == "uint16": value = value.astype("int32") elif value.dtype == "uint32": value = value.astype("int64") # Return raw image without any corrections if raw: return value return transform_image(value, self.camera_config)
def _get_image(self, value, raw=False): if value is None: return None # Shape image value = value[:(self.width_raw * self.height_raw)].reshape( (self.height_raw, self.width_raw)) # Return raw image without any corrections if raw: return value return transform_image(value, self.camera_config)
def _collect_camera_settings(self): try: #self.width_raw, self.height_raw = 659, 494 source_host, source_port = get_host_port_from_stream_address(self.bsread_stream_address) stream = Source(host=source_host, port=source_port, mode=PULL,receive_timeout=3000) stream.connect() data = stream.receive() image = data.data.data[self.camera_config.get_source() + config.EPICS_PV_SUFFIX_IMAGE].value if image is None: self.height_raw, self.width_raw = 0,0 else: image = transform_image(image, self.camera_config) self.height_raw, self.width_raw = image.shape except: raise RuntimeError("Could not fetch camera settings cam_server:{}".format(self.camera_config.get_source())) finally: stream.disconnect()
def get_image(self, raw=False): value = self.read() # Return raw image without any corrections if raw: return value return transform_image(value, self.camera_config)
def process_bsread_camera(stop_event, statistics, parameter_queue, camera, port): """ Start the camera stream and receive the incoming bsread streams. This function blocks until stop_event is set. :param stop_event: Event when to stop the process. :param statistics: Statistics namespace. :param parameter_queue: Parameters queue to be passed to the pipeline. :param camera: Camera instance to get the stream from. :param port: Port to use to bind the output stream. """ sender = None camera_stream = None try: # If there is no client for some time, disconnect. def no_client_timeout(): _logger.info( "No client connected to the '%s' stream for %d seconds. Closing instance." % (camera.get_name(), config.MFLOW_NO_CLIENTS_TIMEOUT)) stop_event.set() def process_parameters(): nonlocal x_size, y_size, x_axis, y_axis x_axis, y_axis = camera.get_x_y_axis() x_size, y_size = camera.get_geometry() # TODO: Use to register proper channels. But be aware that the size and dtype can change during the running. # def register_image_channel(size_x, size_y, dtype): # sender.add_channel("image", metadata={"compression": config.CAMERA_BSREAD_IMAGE_COMPRESSION, # "shape": [size_x, size_y], # "type": dtype}) x_size = y_size = x_axis = y_axis = None sender = Sender(port=port, mode=PUB, data_header_compression=config. CAMERA_BSREAD_DATA_HEADER_COMPRESSION) sender.open(no_client_action=no_client_timeout, no_client_timeout=config.MFLOW_NO_CLIENTS_TIMEOUT) camera_name = camera.get_name() camera_stream = camera.get_stream() _logger.info("Connecting to camera '%s' over bsread.", camera_name) process_parameters() # register_image_channel(x_size, y_size, dtype) statistics.counter = 0 camera_stream.connect() # This signals that the camera has successfully started. stop_event.clear() while not stop_event.is_set(): try: data = camera_stream.receive() # In case of receiving error or timeout, the returned data is None. if data is None: continue image = data.data.data[camera_name + config.EPICS_PV_SUFFIX_IMAGE].value # Rotate and mirror the image if needed - this is done in the epics:_get_image for epics cameras. image = transform_image(image, camera.camera_config) # Numpy is slowest dimension first, but bsread is fastest dimension first. height, width = image.shape pulse_id = data.data.pulse_id timestamp_s = data.data.global_timestamp timestamp_ns = data.data.global_timestamp_offset timestamp = timestamp_s + (timestamp_ns / 1e9) data = { "image": image, "height": height, "width": width, "x_axis": x_axis, "y_axis": y_axis, "timestamp": timestamp } sender.send(data=data, pulse_id=pulse_id, timestamp=timestamp, check_data=True) while not parameter_queue.empty(): new_parameters = parameter_queue.get() camera.camera_config.set_configuration(new_parameters) process_parameters() except Exception as e: _logger.exception("Could not process message.", e) stop_event.set() _logger.info("Stopping transceiver.") except Exception as e: _logger.exception("Error while processing camera stream.", e) finally: # Wait for termination / update configuration / etc. stop_event.wait() if camera_stream: camera.disconnect() if sender: sender.close()
def process_stream(camera_stream, index): nonlocal total_bytes, last_pid, frame_shape, format_error, data_format_changed try: if stop_event.is_set(): return False data = camera_stream.receive() #def on_format_error(): # camera_stream.format_error_counter = camera_stream.format_error_counter + 1 # _logger.warning( # "Invalid image format: retry %d of %d [%s]" % ( # camera_stream.format_error_counter, config.FORMAT_ERROR_COUNT, camera.get_name())) # if camera_stream.format_error_counter >= config.FORMAT_ERROR_COUNT: # raise Exception("Invalid image format") if data is not None: image = data.data.data[camera_name + config.EPICS_PV_SUFFIX_IMAGE].value if image is None: format_error = True #on_format_error() return True else: # Rotate and mirror the image if needed - this is done in the epics:_get_image for epics cameras. image = transform_image(image, camera.camera_config) # Numpy is slowest dimension first, but bsread is fastest dimension first. height, width = image.shape if (len(x_axis) != width) or (len(y_axis) != height): format_error = True #on_format_error() return True format_error = False #camera_stream.format_error_counter = 0 frame_shape = str(width) + "x" + str( height) + "x" + str(image.itemsize) total_bytes[ index] = data.statistics.total_bytes_received with stats_lock: set_statistics(statistics, sender, sum(total_bytes), 1 if data else 0, frame_shape) # In case of receiving error or timeout, the returned data is None. if data is None: return True pulse_id = data.data.pulse_id if not threaded: if connections > 1: if last_pid: if pulse_id != (last_pid + pid_offset): _logger.warning( "Wrong pulse offset: realigning streams last=%d current=%d [%s]" % (last_pid, pulse_id, camera.get_name())) align_streams() last_pid = None return False last_pid = pulse_id timestamp_s = data.data.global_timestamp timestamp_ns = data.data.global_timestamp_offset timestamp = timestamp_s + (timestamp_ns / 1e9) data = { "image": image, "height": height, "width": width, "x_axis": x_axis, "y_axis": y_axis, "timestamp": timestamp } if threaded: with message_buffer_lock: message_buffer[pulse_id] = (data, timestamp) else: sender.send(data=data, pulse_id=pulse_id, timestamp=timestamp, check_data=data_format_changed) data_format_changed = False on_message_sent(statistics) except Exception as e: _logger.error("Could not process message: %s [%s]" % (str(e), camera.get_name())) exit_code = 3 stop_event.set() return True