예제 #1
0
    def connect(self, sn):
        """Connect to the camera with the given serial number.

        :param str sn: Camera serial number.
        """
        self.sdk = TLCameraSDK()
        self.camera = self.sdk.open_camera(sn)

        self._sn = self.camera.serial_number
        self._model = self.camera.model

        self._swidth = self.camera.sensor_width_pixels
        self._sheight = self.camera.sensor_height_pixels
        self._rgb = (self.camera.camera_sensor_type == 1)
        self._bitsperpixel = self.camera.bit_depth
        logger.info(
            ("Sensor: %d x %d pixels, RGB = %d, %d bits/px" %
             (self._swidth, self._sheight, self._rgb, self._bitsperpixel)))

        self.camera.operation_mode = 0  # software-triggered
        self.camera.frames_per_trigger_zero_for_unlimited = 1  # single frame per trigger
        self.camera.is_frame_rate_control_enabled = False  # disable frame rate control

        self.fpsmin = self.camera.frame_rate_control_value_range.min  # min fps
        self.fpsmax = self.camera.frame_rate_control_value_range.max  # max fps

        self.expmin = self.camera.exposure_time_range_us.min / 1000.  # exposure min in ms
        self.expmax = self.camera.exposure_time_range_us.max / 1000.  # exposure max in ms
        logger.info(("Valid exposure times: %fms to %fms" %
                     (self.expmin, self.expmax)))
        self.set_exposure(self.expmin)  # set exposure to min value

        self.camera.image_poll_timeout_ms = 5000  # 5 second polling timeout

        self.camera.arm(2)  # arm the camera with a two-frame buffer
예제 #2
0
    def __init__(self):
        #variables
        self.FILECOUNTER = 0
        self.counter = 0  # 0 = background Image ; 1 = wave Image
        self.singleTriggerMode = True
        self.maxIntensity = 65536
        self.minIntensity = 0

        #open camera and setup settings:
        self.sdk = TLCameraSDK()
        cameras = self.sdk.discover_available_cameras()
        if len(cameras) == 0:
            print("Error: no cameras detected!")

        self.camera = self.sdk.open_camera(cameras[0])
        self.camera.frames_per_trigger_zero_for_unlimited = 1
        self.camera.operation_mode = OPERATION_MODE.BULB  # set Hardwaretrigger
        self.camera.trigger_polarity = TRIGGER_POLARITY.ACTIVE_HIGH  # Trigger auf active HIGH
        #self.camera.exposure_time_us = 10
        print("Exposure Time :", self.camera.exposure_time_us)
        print("Bit Depth: ", self.camera.bit_depth)
        print(self.camera.operation_mode)
        print(self.camera.trigger_polarity)
        self.camera.image_poll_timeout_ms = 1000  # 1 second timeout
        self.camera.arm(2)
예제 #3
0
class Camera():

    # Initialize SDK and Camera objects in order to use ThorLabs API functions
    def __init__(self):
        self.camSesh = TLCameraSDK()
        camList = self.camSesh.discover_available_cameras()
        camSerialNum = '08153'
        self.cam = self.camSesh.open_camera(camSerialNum)
        self.cam.operation_mode = thorlabs_tsi_sdk.tl_camera_enums.OPERATION_MODE.SOFTWARE_TRIGGERED
        # Set camera exposure in units of microseconds
        expose_time = 36
        self.cam.exposure_time_us = expose_time
        self.cam.frames_per_trigger_zero_for_unlimited = 1
        self.isStreaming = False

    # Call destructors for SDK and Camera objects
    def __del__(self):
        self.cam.dispose()
        self.camSesh.dispose()

    # Takes a picture and returns an np.array of the image
    def takePicture(self):
        self.cam.frames_per_trigger_zero_for_unlimited = 1
        self.cam.arm(1)
        self.cam.issue_software_trigger()
        temp = self.cam.get_pending_frame_or_null()
        image = np.copy(temp.image_buffer)
        # Extract middle of x coordinates to get square photo (photos are 4096x2160)
        image = image[:, 968:3128]
        self.cam.disarm()
        return image

    # Initialize camera for video recording
    def startVideoStream(self):
        if self.isStreaming:
            print("Video is already streaming")
            return None
        self.isStreaming = True
        self.cam.frames_per_trigger_zero_for_unlimited = 0
        self.cam.arm(1)
        self.cam.issue_software_trigger()
        self.vidThread = threading.Thread(target=self.getVideoStream)
        self.vidThread.start()
        return self

    # Start
    def getVideoStream(self):
        temp = self.cam.get_pending_frame_or_null()
        image = np.copy(temp.image_buffer)
        image = image[:, 968:3128]
        return image

    # End a video feed for a camera
    def endVideoStream(self):
        self.isStreaming = False
        self.vidThread.join()
        self.cam.frames_per_trigger_zero_for_unlimited = 1
        self.cam.disarm()
예제 #4
0
 def __init__(self):
     self.camSesh = TLCameraSDK()
     camList = self.camSesh.discover_available_cameras()
     camSerialNum = '08153'
     self.cam = self.camSesh.open_camera(camSerialNum)
     self.cam.operation_mode = thorlabs_tsi_sdk.tl_camera_enums.OPERATION_MODE.SOFTWARE_TRIGGERED
     # Set camera exposure in units of microseconds
     expose_time = 36
     self.cam.exposure_time_us = expose_time
     self.cam.frames_per_trigger_zero_for_unlimited = 1
     self.isStreaming = False
예제 #5
0
class ThorcamHost:
    def __init__(self):
        self.camera_sdk = TLCameraSDK()
        self.discover_cameras()
        self.mono2color_sdk = MonoToColorProcessorSDK()

    def discover_cameras(self):
        self.available_cameras = self.camera_sdk.discover_available_cameras()
        if len(self.available_cameras) < 1:
            raise ValueError("no cameras detected")

    def spawn_camera(self, camid=None):
        if camid is None:
            if len(self.available_cameras) == 1:
                camid = self.available_cameras[0]
            else:
                camid = self.__user_select_camera()
        return Thorcam(camid, host=self)

    def __user_select_camera(self):
        print("Select camera:")
        for i, sn in enumerate(self.available_cameras):
            print(f"\t{i}: {sn}")
        selection = int(input("Enter index of camera you want: "))
        if selection >= len(self.available_cameras):
            raise ValueError(
                f"Index {selection} is out of range (0-{len(self.available_cameras)})!"
            )
        return self.available_cameras[selection]
예제 #6
0
 def get_cameras(self):
     """Finds the connected TSI cameras.
     """
     with TLCameraSDK() as sdk:
         available_cameras = sdk.discover_available_cameras()
     nCams = len(available_cameras)
     logger.info(("Found %d tsi camera(s)" % nCams))
     if nCams > 0:
         self._cam_list = available_cameras
예제 #7
0
    def activate(self,quiet=False):
        
        # begin camera id block
        self.userChoseStream = False
        validCamRange = [None, None]
        
        self.camera_sdk = TLCameraSDK()
        self.mono_to_color_sdk = MonoToColorProcessorSDK()
        
        try:
            self.available_cameras = self.camera_sdk.discover_available_cameras()
        except UnicodeDecodeError:
            cprint("Thorlabs SDK Error: Please power cycle camera",'red',attrs=['bold'])
            exit()
            
        if len(self.available_cameras) < 1:
            cprint("no cameras detected! Check udev rules",'red',attrs=['bold'])
            return
        elif len(self.available_cameras) > 1:
            for i in range(len(self.available_cameras)):
                print("%i: %s" % (i,self.available_cameras[i]))
            while not self.params['ID'] in validCamRange:
                try:
                    self.params['ID']=int(raw_input("\tPlease select camera ID [0-%i]:" % (len(self.available_cameras)-1)))
                    self.userChoseStream = True
                except:
                    pass
        else:
            self.params['ID']=0
        
        # End camera id block
        
        # Set up configuration for number of frames to capture per query event
        
        if 'n_frames' in self.params: self.config['n_frames'] = self.params['n_frames']
        else: self.config['n_frames'] = 1
        
        # Make first query to get units, description, etc.
        self.query(reset=True)

        if not quiet: self.pprint()
        return
예제 #8
0
class TLCamera:
    def __init__(self, timeout=500):
        self.sdk = TLCameraSDK()
        cameralist = self.sdk.discover_available_cameras()
        if len(cameralist) == 0:
            print("Error: no cameras detected!")

        self.camera = self.sdk.open_camera(cameralist[0])
        #  setup the camera for continuous acquisition
        self.camera.frames_per_trigger_zero_for_unlimited = 0
        self.camera.image_poll_timeout_ms = 2000  # 2 second timeout
        self.camera.arm(2)
        self.camera.exposure_time_us = 100

        # save these values to place in our custom TIFF tags later
        bit_depth = self.camera.bit_depth
        exposure = self.camera.exposure_time_us

        # need to save the image width and height for color processing
        image_width = self.camera.image_width_pixels
        image_height = self.camera.image_height_pixels
        print(image_width)
        print(image_height)
        self.image = None

    def get_image(self):
        self.camera.issue_software_trigger()
        frame = self.camera.get_pending_frame_or_null()
        self.image = frame.image_buffer
        return self.image

    def close(self):
        self.camera.disarm()
        return

    def set_exposure(self, exposure_us):
        self.camera.exposure_time_us = exposure_us
        return

    def get_exposure(self):
        return self.camera.exposure_time_us
예제 #9
0
    def __init__(self, timeout=500):
        self.sdk = TLCameraSDK()
        cameralist = self.sdk.discover_available_cameras()
        if len(cameralist) == 0:
            print("Error: no cameras detected!")

        self.camera = self.sdk.open_camera(cameralist[0])
        #  setup the camera for continuous acquisition
        self.camera.frames_per_trigger_zero_for_unlimited = 0
        self.camera.image_poll_timeout_ms = 2000  # 2 second timeout
        self.camera.arm(2)
        self.camera.exposure_time_us = 100

        # save these values to place in our custom TIFF tags later
        bit_depth = self.camera.bit_depth
        exposure = self.camera.exposure_time_us

        # need to save the image width and height for color processing
        image_width = self.camera.image_width_pixels
        image_height = self.camera.image_height_pixels
        print(image_width)
        print(image_height)
        self.image = None
예제 #10
0
class TSI_Library:
    """Builds the functionality of the Thorlabs Scientific Imaging (TSI) camera SDK library.
    """
    def __init__(self):
        """Constructor.

        Takes no arguments but tries to automatically configure the system path and
        creates a list of all connected cameras.
        """
        self._cam_list = []
        self._sn = None
        self._model = None
        self._swidth = 0
        self._sheight = 0
        self._rgb = 0

        self._image = None
        self._imgID = None

        self.configure_path()
        self.get_cameras()

    def configure_path(self):
        """Configure the system path to include the directory containing the dlls.

        User must specify the correct path for the indicated variable within the function code.
        """
        logger.debug("Configure system path..")

        is_64bits = sys.maxsize > 2**32

        # change the value below to define dll system path
        path_to_dlls = r"C:\Program Files\Thorlabs\Scientific Imaging\Scientific Camera Support"\
                       r"\Scientific_Camera_Interfaces-Rev_G\Scientific Camera Interfaces\SDK"\
                       r"\Native Compact Camera Toolkit\dlls"

        if is_64bits:
            path_to_dlls += r"\Native_64_lib"
        else:
            path_to_dlls += r"\Native_32_lib"

        os.environ['PATH'] = path_to_dlls + os.pathsep + os.environ['PATH']

        logger.info((path_to_dlls + " added to system path"))

    def get_cameras(self):
        """Finds the connected TSI cameras.
        """
        with TLCameraSDK() as sdk:
            available_cameras = sdk.discover_available_cameras()
        nCams = len(available_cameras)
        logger.info(("Found %d tsi camera(s)" % nCams))
        if nCams > 0:
            self._cam_list = available_cameras

    def connect(self, sn):
        """Connect to the camera with the given serial number.

        :param str sn: Camera serial number.
        """
        self.sdk = TLCameraSDK()
        self.camera = self.sdk.open_camera(sn)

        self._sn = self.camera.serial_number
        self._model = self.camera.model

        self._swidth = self.camera.sensor_width_pixels
        self._sheight = self.camera.sensor_height_pixels
        self._rgb = (self.camera.camera_sensor_type == 1)
        self._bitsperpixel = self.camera.bit_depth
        logger.info(
            ("Sensor: %d x %d pixels, RGB = %d, %d bits/px" %
             (self._swidth, self._sheight, self._rgb, self._bitsperpixel)))

        self.camera.operation_mode = 0  # software-triggered
        self.camera.frames_per_trigger_zero_for_unlimited = 1  # single frame per trigger
        self.camera.is_frame_rate_control_enabled = False  # disable frame rate control

        self.fpsmin = self.camera.frame_rate_control_value_range.min  # min fps
        self.fpsmax = self.camera.frame_rate_control_value_range.max  # max fps

        self.expmin = self.camera.exposure_time_range_us.min / 1000.  # exposure min in ms
        self.expmax = self.camera.exposure_time_range_us.max / 1000.  # exposure max in ms
        logger.info(("Valid exposure times: %fms to %fms" %
                     (self.expmin, self.expmax)))
        self.set_exposure(self.expmin)  # set exposure to min value

        self.camera.image_poll_timeout_ms = 5000  # 5 second polling timeout

        self.camera.arm(2)  # arm the camera with a two-frame buffer

    def disconnect(self):
        """Disconnect a currently connected camera.
        """
        self.camera.disarm()
        self.camera.dispose()
        self.sdk.dispose()

    def get_pixel_width(self):
        """Gets pixel width in microns.
        """
        return self.camera.sensor_pixel_width_um

    def get_sensor_size(self):
        """Returns the sensor size in pixels as a tuple: (width, height)

        If not connected yet, it returns a zero tuple.
        """
        return self._swidth, self._sheight

    def get_image_size(self):
        """Returns the image size in pixels as a tuple: (width, height)
        """
        return self.camera.image_width_pixels, self.camera.image_height_pixels

    def get_frame_rate_limits(self):
        """Returns the frame rate limits in fps (min, max, increment=0.1).
        """
        return self.camera.frame_rate_control_value_range.min, self.camera.frame_rate_control_value_range.max, 0.1

    def set_gain(self, gain):
        """Set the hardware gain.

        :param int gain: New gain setting.
        """
        self.camera.gain = int(gain)

    def get_gain(self):
        """Returns current gain setting.
        """
        return self.camera.gain

    def get_gain_limits(self):
        """Returns gain limits (min, max, increment=1).
        """
        return self.camera.gain_range.min, self.camera.gain_range.max, 1

    def set_blacklevel(self, blck):
        """Set blacklevel.

        :param int blck: New blacklevel setting.
        """
        self.camera.black_level = int(blck)

    def get_blacklevel_limits(self):
        """Returns blacklevel limts (min, max).
        """
        return self.camera.black_level_range.min, self.camera.black_level_range.max

    def set_exposure(self, exp):
        """Set exposure time in milliseconds.

        :param int exp: New exposure time.
        """
        self.camera.exposure_time_us = int(exp * 1000)

    def get_exposure(self):
        """Returns current exposure time in milliseconds.
        """
        return self.camera.exposure_time_us / 1000.

    def get_exposure_limits(self):
        """Returns the supported limits for the exposure time in ms (min, max, increment).
        """
        _min = self.camera.exposure_time_range_us.min / 1000.  # exposure min in ms
        _max = self.camera.exposure_time_range_us.max / 1000.  # exposure max in ms

        if self.camera.usb_port_type == 2:
            inc = 1000 / (1125 * self.camera.frame_rate_control_value_range.max
                          )  # exposure step size for usb3.0
        else:
            inc = 1000 / (582 * self.camera.frame_rate_control_value_range.max
                          )  # exposure step size for usb2.0

        return _min, _max, inc

    def set_roi(self, posx, posy, width, height):
        """Set the ROI.
        """
        self.camera.roi = (posx, posy, width + posx, height + posy)

    def get_roi(self):
        """Returns the current ROI.
        """
        return self.camera.roi

    def arm(self, N=2):
        """Arms the camera with an N-frame buffer.
        """
        self.camera.arm(N)

    def trigger(self):
        """Issues a software trigger.
        """
        self.camera.issue_software_trigger()

    def disarm(self):
        """Disarms the camera.
        """
        self.camera.disarm()

    def get_is_armed(self):
        """Returns True if the camera is armed, False if unarmed.
        """
        return self.camera.is_armed

    def acquire(self, N=1, native=False):
        """Synchronously captures some frames from the camera using the current settings and returns the averaged image.

        :param int N: Number of frames to acquire (>= 1).
        :returns: Averaged image.
        """
        logger.debug(("acquire %d frames" % N))
        data = None

        for i in range(int(N)):
            self.camera.issue_software_trigger()
            logger.debug("  wait for data..")
            frame = self.camera.get_pending_frame_or_null()
            self._image = frame.image_buffer
            self._imgID = frame.frame_count
            logger.debug("  read data..")
            if data is None:
                if native:
                    data = self._image
                else:
                    data = self._image.astype(float)
            else:
                data = data + self._image
        if not native:
            data = data / float(N)

        return data

    def acquireBinned(self, N=1):
        """Record N frames from the camera using the current settings and return fully binned 1d arrays averaged over the N frames.

        :param int N: Number of images to acquire.
        :returns: - Averaged 1d array fully binned over the x-axis.
                  - Averaged 1d array fully binned over the y-axis.
                  - Maximum pixel intensity before binning, e.g. to detect over illumination.
        """
        data = self.acquire(N)
        return np.sum(data, axis=0), np.sum(data, axis=1), np.amax(data)

    def acquireMax(self, N=1):
        """Record N frames from the camera using the current settings and return the column / row with the maximum intensity.

        :param int N: Number of images to acquire.
        :returns: - Column with maximum intensity (1d array).
                  - Row with maximum intensity (1d array).
        """
        data = self.acquire(N)
        return data[
            np.argmax(np.data, axis=0), :], data[:,
                                                 np.argmax(np.data, axis=1)]
from thorlabs_tsi_sdk.tl_mono_to_color_processor import MonoToColorProcessorSDK
from thorlabs_tsi_sdk.tl_camera_enums import SENSOR_TYPE

NUMBER_OF_IMAGES = 10  # Number of TIFF images to be saved
OUTPUT_DIRECTORY = os.path.abspath(
    r'.')  # Directory the TIFFs will be saved to
FILENAME = 'image.tif'  # The filename of the TIFF

TAG_BITDEPTH = 32768
TAG_EXPOSURE = 32769

# delete image if it exists
if os.path.exists(OUTPUT_DIRECTORY + os.sep + FILENAME):
    os.remove(OUTPUT_DIRECTORY + os.sep + FILENAME)

with TLCameraSDK() as sdk:
    cameras = sdk.discover_available_cameras()
    if len(cameras) == 0:
        print("Error: no cameras detected!")

    with sdk.open_camera(cameras[0]) as camera:
        #  setup the camera for continuous acquisition
        camera.frames_per_trigger_zero_for_unlimited = 0
        camera.image_poll_timeout_ms = 2000  # 2 second timeout
        camera.arm(2)

        # save these values to place in our custom TIFF tags later
        bit_depth = camera.bit_depth
        exposure = camera.exposure_time_us

        # need to save the image width and height for color processing
예제 #12
0
class thorcamDevice(device):
    """ Class providing support for Thorlabs scientific cameras.
    """

    def __init__(self,params={},quiet=True,**kwargs):
        self.config = {} # user-variable configuration parameters go here (ie scale, offset, eng. units)
        self.params = params # fixed configuration paramaters go here (ie USB PID & VID, raw device units)
        self.driverConnected = False # Goes to True when scan method succeeds
        self.name = "uninitialized"
        self.lastValue = None # Last known value (for logging)
        self.lastValueTimestamp = None # Time when last value was obtained
        self.driver = self.params['driver'].split('/')[1:]
        self.quiet = quiet
        
        if not 'live_preview' in self.params:
            if not 'live_preview' in kwargs:
                self.live_preview=False
            else: self.live_preview=kwargs['live_preview']
        else: self.live_preview=self.params['live_preview']
            
        if not 'ID' in self.params: self.params['ID'] = None # default OpenCV camera ID number
        if not 'debugMode' in self.params: self.params['debugMode']=False
        
        if params is not {}: self.scan(quiet=quiet)
        
        return

    # Detect if device is present
    def scan(self,override_params=None,quiet=False):
        
        if override_params is not None: self.params = override_params
        
        # check USB device exists
        try:
            self.usbdev = usb.core.find(idVendor=self.params['vid'], idProduct=self.params['pid'])
            self.activate(quiet=quiet)
        except:
            raise
        
        return

    # Establish connection to device
    def activate(self,quiet=False):
        
        # begin camera id block
        self.userChoseStream = False
        validCamRange = [None, None]
        
        self.camera_sdk = TLCameraSDK()
        self.mono_to_color_sdk = MonoToColorProcessorSDK()
        
        try:
            self.available_cameras = self.camera_sdk.discover_available_cameras()
        except UnicodeDecodeError:
            cprint("Thorlabs SDK Error: Please power cycle camera",'red',attrs=['bold'])
            exit()
            
        if len(self.available_cameras) < 1:
            cprint("no cameras detected! Check udev rules",'red',attrs=['bold'])
            return
        elif len(self.available_cameras) > 1:
            for i in range(len(self.available_cameras)):
                print("%i: %s" % (i,self.available_cameras[i]))
            while not self.params['ID'] in validCamRange:
                try:
                    self.params['ID']=int(raw_input("\tPlease select camera ID [0-%i]:" % (len(self.available_cameras)-1)))
                    self.userChoseStream = True
                except:
                    pass
        else:
            self.params['ID']=0
        
        # End camera id block
        
        # Set up configuration for number of frames to capture per query event
        
        if 'n_frames' in self.params: self.config['n_frames'] = self.params['n_frames']
        else: self.config['n_frames'] = 1
        
        # Make first query to get units, description, etc.
        self.query(reset=True)

        if not quiet: self.pprint()
        return

    # Deactivate connection to device (close serial port)
    def deactivate(self):
        self.driverConnected=False
        del self.opencvdev
        return

    # Apply configuration changes to the driver (subdriver-specific)
    def apply_config(self):
        subdriver = self.params['driver'].split('/')[1:]
        try:
            assert(self.deviceClass)
            if self.deviceClass is None: raise pyLabDataLoggerIOError("Could not access device.")
            
            # Apply subdriver-specific variable writes
            if subdriver=='?':
                #...
                pass
            else:
                raise RuntimeError("I don't know what to do with a device driver %s" % self.params['driver'])
        
        except ValueError:
            cprint( "%s - Invalid setting requested" % self.name, 'red', attrs=['bold'])
        
        return

    # Update configuration (ie change sample rate or number of samples)
    def update_config(self,config_keys={}):
        for key in config_keys.keys():
            self.config[key]=self.config_keys[key]
        self.apply_config()
        return

    def updateTimestamp(self):
        self.lastValueTimestamp = datetime.datetime.now()

    # Re-establish connection to device.
    def reset(self):
        self.deactivate()
        self.scan()
        if self.driverConnected: self.activate()
        else: cprint( "Error resetting %s: device is not detected" % self.name, 'red', attrs=['bold'])
   

    # Handle query for values
    def query(self, reset=False):

        
        # If first time or reset, get configuration (ie units)
        if not 'raw_units' in self.params.keys() or reset:

            # Set up device
            self.name = self.params['name'] # from usbDevice lookup table, usb descriptor data often empty
            if self.config['n_frames'] == 1: self.config['channel_names']=['Image']
            else: self.config['channel_names']=['Frame %i' % j  for j in range(self.config['n_frames'])]
            self.params['raw_units']=['Intensity']
            self.config['eng_units']=['Intensity']
            self.config['scale']=[1.]
            self.config['offset']=[0.]
            self.params['n_channels']=self.config['n_frames']
            self.frame_counter = -1 # reset frame counter. It'll be incremented up to zero before the first save.
            
            # Try to open camera stream.
            self.camera =  self.camera_sdk.open_camera(self.available_cameras[self.params['ID']])
            self.camera.frames_per_trigger_zero_for_unlimited = 0  # start camera in continuous mode
            self.camera.image_poll_timeout_ms = 2000  # 2 second timeout
            self.driverConnected=True
            
            # Setup post-processor for colour images
            self.mono_to_color_processor = self.mono_to_color_sdk.create_mono_to_color_processor(
                self.camera.camera_sensor_type,
                self.camera.color_filter_array_phase,
                self.camera.get_color_correction_matrix(),
                self.camera.get_default_white_balance_matrix(),
                self.camera.bit_depth)
            self.mono_to_color_processor.color_space = COLOR_SPACE.SRGB  # sRGB color space
            self.mono_to_color_processor.output_format = FORMAT.RGB_PIXEL  # data is returned as sequential RGB values
            self.params['red gain']=red_gain=self.mono_to_color_processor.red_gain
            self.params['green gain']=green_gain=self.mono_to_color_processor.green_gain
            self.params['blue gain']=blue_gain=self.mono_to_color_processor.blue_gain
            
            if self.live_preview:
                self.fig = plt.figure()
                self.ax = self.fig.add_subplot(111)
                self.ax.axis('off')
                #plt.ion()
                plt.show(block=False)
                plt.pause(.1)


        # Check
        try:
            assert(self.camera)
            if self.camera is None: raise pyLabDataLoggerIOError
        except:
            cprint( "Connection to the device is not open.", 'red', attrs=['bold'])
        

        # Get Image(s)
        rawFrames = []
        self.camera.arm(self.config['n_frames'])
        self.params['width'] = self.camera.image_width_pixels
        self.params['height'] = self.camera.image_height_pixels
        for j in range(self.config['n_frames']):
            self.camera.issue_software_trigger()
            rawframe = self.camera.get_pending_frame_or_null()
            self.frame_counter += 1 # increment counter even if image not returned
            rawFrames.append(rawframe)
            if rawframe is None:
                cprint("\tNo frame arrived from Thorlabs camera within the timeout!",'red')
        self.camera.disarm()
            
        if not self.quiet:
            cprint("\tCaptured %i/%i frames" % (len([f for f in rawFrames if f is not None]),self.config['n_frames']),'green')
        
        # Post process image(s)
        self.lastValue=[]
        livePreviewImg=None
        for rawframe in rawFrames:
            if rawframe is None:
                self.lastValue.append(np.nan)
            else:
                # this will give us a resulting image with 3 channels (RGB) and 16 bits per channel, resulting in 48 bpp
                color_image_16bit = self.mono_to_color_processor.transform_to_48(rawframe.image_buffer, self.params['width'], self.params['height'])
                # this will give us a resulting image with 4 channels (RGBA) and 8 bits per channel, resulting in 32 bpp
                #color_image = self.mono_to_color_processor.transform_to_32((rawframe.image_buffer, self.params['width'], self.params['height'])
                # this will give us a resulting image with 3 channels (RGB) and 8 bits per channel, resulting in 24 bpp
                color_image_8bit = self.mono_to_color_processor.transform_to_24(rawframe.image_buffer, self.params['width'], self.params['height'])
                # copy to lastValue
                if livePreviewImg is None: livePreviewImg = color_image_8bit[...].reshape(self.params['height'], self.params['width'], 3)
                self.lastValue.append(color_image_16bit[...].reshape(self.params['height'], self.params['width'], 3))
                
        # Set up live preview mode if requested
        if self.live_preview:
            cprint("\tlive_preview: displaying frame_%08i %s" % (self.frame_counter,livePreviewImg.shape), 'green')
            try:
                assert self.imshow
                self.imshow.set_data(livePreviewImg)
            except:
                self.imshow = self.ax.imshow(livePreviewImg)

            try:
                self.ax.set_title("Frame %06i : %s" % (self.frame_counter,self.lastValueTimestamp))
                self.fig.canvas.draw()
                #plt.show(block=False)
                plt.pause(0.01) # 10 ms for window to refresh itself.
            except:
                cprint( "\tError updating Thorlabs preview window", 'red', attrs=['bold'])

        # Generate scaled values. Convert non-numerics to NaN
        lastValueSanitized = []
        for v in self.lastValue: 
            if v is None: lastValueSanitized.append(np.nan)
            else: lastValueSanitized.append(v)
        self.lastScaled = np.array(lastValueSanitized) * self.config['scale'] + self.config['offset']
        self.updateTimestamp()
        return self.lastValue


    # log to HDF5 file - overload function
    def log_hdf5(self, filename, max_records=None):
        try:
            import h5py
        except ImportError:
            cprint( "Please install h5py", 'red', attrs=['bold'])
            return
        
        # Open file
        with h5py.File(filename, 'a') as fh:

            # Load group for this device.
            if 'name' in self.config: devname = self.config['name']
            elif 'name' in self.params: devname = self.params['name']
            else: devname = self.name
            if devname in fh: dg = fh[devname]
            else:
                dg = fh.create_group(devname)
                # On creation, add attributes from config and params
                for attr in self.params.keys():
                    dg.attrs[attr] = repr(self.params[attr])
                for attr in self.config.keys():
                    dg.attrs[attr] = repr(self.config[attr])

            # Create/update timestamp dataset
            # Each device has a lastValueTimestamp which can vary a bit between devices due to latency issues.
            if 'timestamp' in dg:
                td = dg['timestamp']
                td.resize([td.shape[0]+1,])
                td[-1] = str(self.lastValueTimestamp)
            else:
                dg.create_dataset('timestamp',data=[str(self.lastValueTimestamp)],maxshape=(max_records,))


            # Write images into dg...
            for j in range(len(self.lastValue)):
                dsname = 'frame_%08i' % (self.frame_counter-len(self.lastValue)+j+1)
                if dsname in dg:
                    cprint( "\tOverwriting image %s in HDF5 log file!" % dsname, 'yellow')
                    del dg[dsname]
                
                # Flip colours in dataset - 21/5/20
                # Swap to uint16, this might not work in HDFView but keep all the bits anyway! 17/9/20
                dset=dg.create_dataset(dsname, data=np.flip(self.lastValue[j],axis=2), dtype='uint16', chunks=True,\
                                        compression='gzip', compression_opts=1) # apply fast compression
                
                #Set the image attributes
                dset.attrs.create('CLASS', 'IMAGE')
                dset.attrs.create('IMAGE_VERSION', '1.2')
                dset.attrs.create('IMAGE_SUBCLASS', 'IMAGE_TRUECOLOR')
                dset.attrs.create('INTERLACE_MODE', 'INTERLACE_PIXEL')
                #dset.attrs['IMAGE_COLORMODEL'] = 'RGB'
            
            fh.close()

    # log to text file - overload function
    def log_text(self, filename):
        # In "text" mode, perhaps just save a JPEG file?
        raise RuntimeError("Not implemented")
예제 #13
0
 def __init__(self):
     self.camera_sdk = TLCameraSDK()
     self.discover_cameras()
     self.mono2color_sdk = MonoToColorProcessorSDK()
예제 #14
0
    # if on Windows, use the provided setup script to add the DLLs folder to the PATH
    from examples.windows_setup import configure_path
    configure_path()
except ImportError:
    configure_path = None

from thorlabs_tsi_sdk.tl_camera import TLCameraSDK
from thorlabs_tsi_sdk.tl_mono_to_color_processor import MonoToColorProcessorSDK
from thorlabs_tsi_sdk.tl_mono_to_color_enums import COLOR_SPACE
from thorlabs_tsi_sdk.tl_color_enums import FORMAT
"""
    The MonoToColorProcessorSDK and MonoToColorProcessor objects can be used with context managers for automatic 
    clean up. This multi-context-manager 'with' statement opens both the camera sdk and the mono to color sdk at 
    once. 
"""
with TLCameraSDK() as camera_sdk, MonoToColorProcessorSDK(
) as mono_to_color_sdk:
    available_cameras = camera_sdk.discover_available_cameras()
    if len(available_cameras) < 1:
        raise ValueError("no cameras detected")

    with camera_sdk.open_camera(available_cameras[0]) as camera:
        camera.frames_per_trigger_zero_for_unlimited = 0  # start camera in continuous mode
        camera.image_poll_timeout_ms = 2000  # 2 second timeout
        camera.arm(2)
        """
            In a real-world scenario, we want to save the image width and height before color processing so that we 
            do not have to query it from the camera each time it is needed, which would slow down the process. It is 
            safe to save these after arming since the image width and height cannot change while the camera is armed.
        """
        image_width = camera.image_width_pixels
예제 #15
0
class TLCamera():
    def __init__(self):
        #variables
        self.FILECOUNTER = 0
        self.counter = 0  # 0 = background Image ; 1 = wave Image
        self.singleTriggerMode = True
        self.maxIntensity = 65536
        self.minIntensity = 0

        #open camera and setup settings:
        self.sdk = TLCameraSDK()
        cameras = self.sdk.discover_available_cameras()
        if len(cameras) == 0:
            print("Error: no cameras detected!")

        self.camera = self.sdk.open_camera(cameras[0])
        self.camera.frames_per_trigger_zero_for_unlimited = 1
        self.camera.operation_mode = OPERATION_MODE.BULB  # set Hardwaretrigger
        self.camera.trigger_polarity = TRIGGER_POLARITY.ACTIVE_HIGH  # Trigger auf active HIGH
        #self.camera.exposure_time_us = 10
        print("Exposure Time :", self.camera.exposure_time_us)
        print("Bit Depth: ", self.camera.bit_depth)
        print(self.camera.operation_mode)
        print(self.camera.trigger_polarity)
        self.camera.image_poll_timeout_ms = 1000  # 1 second timeout
        self.camera.arm(2)

    def setSingleTriggerMode(self):
        self.singleTriggerMode = True
        cv2.destroyWindow('Live')
        self.camera.image_poll_timeout_ms = 1000  # 1 second timeout

    def setContinuousTriggerMode(self):
        self.singleTriggerMode = False
        cv2.destroyWindow('BGimg_1')
        cv2.destroyWindow('BGimg_2')
        cv2.destroyWindow('WVimg')
        cv2.destroyWindow('DifferenceImage')
        self.camera.image_poll_timeout_ms = 1000

    def setGain(self, value):
        self.camera.gain(value)

    def snapImg(self):
        frame = self.camera.get_pending_frame_or_null()
        if frame is None:
            raise TimeoutError(
                "Timeout was reached while polling for a frame, program will now exit"
            )
        image_data = frame.image_buffer
        #self.ImProc.imageProcess(self.image_data)
        self.showImage(image_data)

    def closeCamera(self):
        self.camera.disarm()
        self.camera.dispose()

    def showSettings(self):
        print("Settings:")
        print("Exposure Time :", self.camera.exposure_time_us)
        print("Bit Depth: ", self.camera.bit_depth)
        print(self.camera.operation_mode)
        print(self.camera.trigger_polarity)

    def showImage(self, image):
        if self.singleTriggerMode == True:
            if self.counter == 0:
                self.BGimg_1 = image
                cv2.imshow("BGimg_1", self.BGimg_1)
                cv2.waitKey(1)
                self.counter = 1
            elif self.counter == 1:
                self.WVimg = image
                cv2.imshow("WVimg", self.WVimg)
                self.Diffimg = cv2.absdiff(self.BGimg_1, self.WVimg)
                self.diff_scaled = cv2.normalize(self.Diffimg,
                                                 None,
                                                 self.minIntensity,
                                                 self.maxIntensity,
                                                 norm_type=cv2.NORM_MINMAX)
                cv2.imshow('DifferenceImage', self.diff_scaled)
                cv2.waitKey(1)
                self.counter = 2
            else:
                self.BGimg_2 = image
                cv2.imshow("BGimg_2", self.BGimg_2)
                cv2.waitKey(1)
                self.counter = 0

        else:
            cv2.imshow("Live", image)
            cv2.waitKey(1)

    def saveImage(self, output_directory):
        tiff = tifffile.TiffWriter(output_directory + os.sep +
                                   str(self.FILECOUNTER).zfill(2) + ".tif",
                                   append=True)
        tiff.save(
            data=self.BGimg_1,  # np.ushort image data array from the camera
            compress=
            0,  # amount of compression (0-9), by default it is uncompressed (0)
            extratags=[
                (TAG_BITDEPTH, 'I', 1, self.camera.bit_depth,
                 False),  # custom TIFF tag for bit depth
                (TAG_EXPOSURE, 'I', 1, self.camera.exposure_time_us, False)
            ]  # custom TIFF tag for exposure
        )
        tiff = tifffile.TiffWriter(output_directory + os.sep +
                                   str(self.FILECOUNTER).zfill(2) + ".tif",
                                   append=True)
        tiff.save(
            data=self.WVimg,  # np.ushort image data array from the camera
            compress=
            0,  # amount of compression (0-9), by default it is uncompressed (0)
            extratags=[
                (TAG_BITDEPTH, 'I', 1, self.camera.bit_depth,
                 False),  # custom TIFF tag for bit depth
                (TAG_EXPOSURE, 'I', 1, self.camera.exposure_time_us, False)
            ]  # custom TIFF tag for exposure
        )
        tiff = tifffile.TiffWriter(output_directory + os.sep +
                                   str(self.FILECOUNTER).zfill(2) + ".tif",
                                   append=True)
        tiff.save(
            data=self.BGimg_2,  # np.ushort image data array from the camera
            compress=
            0,  # amount of compression (0-9), by default it is uncompressed (0)
            extratags=[
                (TAG_BITDEPTH, 'I', 1, self.camera.bit_depth,
                 False),  # custom TIFF tag for bit depth
                (TAG_EXPOSURE, 'I', 1, self.camera.exposure_time_us, False)
            ]  # custom TIFF tag for exposure
        )
        tiff = tifffile.TiffWriter(output_directory + os.sep +
                                   str(self.FILECOUNTER).zfill(2) + ".tif",
                                   append=True)
        tiff.save(
            data=self.Diffimg,  # np.ushort image data array from the camera
            compress=
            0,  # amount of compression (0-9), by default it is uncompressed (0)
            extratags=[
                (TAG_BITDEPTH, 'I', 1, self.camera.bit_depth,
                 False),  # custom TIFF tag for bit depth
                (TAG_EXPOSURE, 'I', 1, self.camera.exposure_time_us, False)
            ]  # custom TIFF tag for exposure
        )
        self.FILECOUNTER = self.FILECOUNTER + 1

    def setMaxIntensity(self, maxIntensity):
        self.maxIntensity = maxIntensity

    def setMinIntensity(self, minIntensity):
        self.minIntensity = minIntensity