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 __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)
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()
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
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]
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 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
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
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
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
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")
def __init__(self): self.camera_sdk = TLCameraSDK() self.discover_cameras() self.mono2color_sdk = MonoToColorProcessorSDK()
# 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
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