예제 #1
0
    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)
예제 #3
0
    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)
예제 #4
0
        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()
예제 #5
0
 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)
예제 #6
0
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()
예제 #7
0
        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