예제 #1
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()
예제 #2
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
예제 #3
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)]
예제 #4
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")
예제 #5
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