Spinnaker SDK and Cooled Cameras - For Distribution - en
Spinnaker SDK and Cooled Cameras - For Distribution - en
This document is a short introduction to the use of Spinnaker SDK - Python - with a FLIR ATS cooled
camera. It is not a training course!
Prerequisites:
Minimum knowledge of the Python programming language, and of the GenICam protocol.
Good knowledge of cooled cameras and how to operate them, for instance with
RIR4Max/ResearchStudio.
Of course, knowledge of infrared imaging, radiometry and thermography.
If you have questions and need to contact the Support Team, submit a ticket at
https://support.flir.com
We are committed to answer, but we cannot develop the solution for you.
Version 1 – En Page 1
Contents
Introduction ............................................................................................................................................ 3
Cooled/photonic cameras from FLIR ATS ........................................................................................... 3
Spinnaker SDK ..................................................................................................................................... 3
Platforms ......................................................................................................................................... 3
Supported languages ...................................................................................................................... 3
Python ............................................................................................................................................. 3
GenICam Processes ............................................................................................................................. 3
Generalities ..................................................................................................................................... 3
FLIR cameras GenICam processes ................................................................................................... 4
Spinnaker BHP vs. BHP SDK. Differences, limitations. ........................................................................ 4
Miscellaneous ..................................................................................................................................... 5
FLIR ATS Camera header ......................................................................................................................... 6
Definition ............................................................................................................................................ 6
Masking the header line ..................................................................................................................... 6
Example of generic code. GigE_Example_Cooled_Visu_Only.py ............................................................ 7
Enumerating factory calibrations............................................................................................................ 8
Loading a factory calibration in a preset............................................................................................... 10
Extracting the maximum and minimum count values for the current factory calibration ................... 11
Extracting the Clock Value .................................................................................................................... 12
Activating Single preset......................................................................................................................... 13
Getting/Setting the frame rate of a preset ........................................................................................... 14
Getting the frame rate ...................................................................................................................... 14
Setting the framerate........................................................................................................................ 14
Activating Superframing mode ............................................................................................................. 15
Preparing Preset Sequencing ................................................................................................................ 16
Activating Preset Sequencing mode ..................................................................................................... 17
Getting/Setting the object parameters ................................................................................................ 18
Setting the Temperature Linear mode ................................................................................................. 19
Retrieving the calibration coefficients, and obtaining radiance and temperature images for a
blackbody .............................................................................................................................................. 20
Version 1 – En Page 2
Introduction
All A and X models are natively GenICam compliant through GigE and CoaXPress (model dependent).
Among the RS models, only the recent RS-85xx ones are GenICam compliant.
Spinnaker SDK
The Spinnaker SDK is FLIR’s next generation GenICam3 API library. It is built around the GenICam
standard, and it is compatible with USB3, 10GigE, and most GigE area scan cameras.
Platforms
Supported platforms:
The current Spinnaker SDK version is 1.29 for Windows and MacOS. And it is 1.27 for Linux.
Supported languages
Spinnaker supports several programming languages:
C
C++
C#
Python
Python
PySpin is a wrapper for the Spinnaker library to allow you to code your application in Python.
GenICam Processes
Generalities
Every GenICam compliant camera has an XML description file. It details camera registers, their
interdependencies, and all other information needed to access high-level features by means of low-
level register read and write operations. The elements of a camera description file are represented
as software objects called nodes. A nodes map is a list of nodes created dynamically at run time.
Version 1 – En Page 3
Regardless of the programming language used, the same node setup applies. Most nodes fall within
seven types. They are:
Type Description
Enumeration Any feature that has a selection of text entries
EnumEntry The individual entry within an enumeration feature
Command Any feature that requires a command to execute
Float Any feature that has a number entry that may include a decimal point
Boolean Any feature that acts as an on or off switch
Integer Any feature that has a number entry without a decimal point
String Any feature that has a user-defined or static text entry
Version 1 – En Page 4
Spinnaker SDK BHP SDK
Any CamLink grabber that
maps the CamLink RS232 port
to a virtual COM port.
FLIR File Support None SAF structure (Read and Write)
C/C++
Supported development
C, C++, C#, Python Partial support for C# and
environments
.NET.
Windows.
Can be compiled for Linux.
For embedded environments
Windows that cannot support high level
Supported OS Linux compiled languages, additional
MacOS documentation is available
that provides details of how to
manually construct the binary
protocol messages.
GigE, GenICam through GigE,
Supported Camera Control GenICam through GigE CamLink, RS232, GenICam
through CoaXPress
Thermographic calibration Enumerate, load and apply Enumerate, load and apply
Factory correction Enumerate, load and apply Enumerate, load and apply
Non Uniformity Correction
Yes Yes
process
Save a state Yes Yes
Counts, temperature when Counts, radiance, temperature
Available units
TempLinear applies (°C, °F, K)
Advanced Graphic User
No, to develop Yes
Interface
Active Support by FLIR Staff
Yes Yes
through Custhelp
Miscellaneous
As written in the Generalities, the system of GenICam nodes is identical regardless of the
programming language used. Therefore, any FLIR cameras that is natively GenICam compliant can be
controlled by any programming language and any operating system: LabView, MATLAB, Halcon,
Cognex, Matrox, etc. Note that performances may vary a lot from one to the other.
Version 1 – En Page 5
FLIR ATS Camera header
Definition
FLIR ATS cooled cameras stream out a header before the image itself. It contains important
information that updated each frame.
The description of the header line can be given upon request. Contact the Support Team through
your support account to get it.
Version 1 – En Page 6
Example of generic code. GigE_Example_Cooled_Visu_Only.py
This code is too long to be inserted here. It is available for free download on Custhelp.
When executed, you get a live video in counts, automatically scaled. A colorbar is placed on the
right-hand side.
Version 1 – En Page 7
Enumerating factory calibrations
Factory calibration files are loaded and indexed in the camera memory. The index varies between
zero and CalibrationQueryIndexMax. The procedure to get details on each of them is:
Example of code.
#Querying a calibration
CalibrationQueryIndexMax_node =
PySpin.CIntegerPtr(nodemap.GetNode('CalibrationQueryIndexMax'))
Index_Max = CalibrationQueryIndexMax_node.GetValue()
print('Index Max = ', Index_Max)
i=0
while i < Index_Max+1:
CalibIndex_node = PySpin.CIntegerPtr(nodemap.GetNode('CalibrationQueryIndex'))
CalibIndex_node.SetValue(i)
node_CalibrationTag = PySpin.CStringPtr(nodemap.GetNode('CalibrationQueryTag'))
CalibrationTag = node_CalibrationTag.GetValue()
print('Calib Index = ', i)
print('Calibration = ', CalibrationTag)
print('-----')
i = i + 1
Index Max = 17
Calib Index = 0
Calibration = 100mm, Empty, -20C - 55C
-----
Calib Index = 1
Calibration = 100mm, Empty, 10C - 90C
-----
Calib Index = 2
Calibration = 100mm, Empty, 150C - 350C
-----
Calib Index = 3
Calibration = 100mm, Empty, 35C - 150C
-----
Calib Index = 4
Calibration = 100mm, Empty, 80C - 200C
-----
Calib Index = 5
Calibration = 25mm, Empty, -20C - 55C
-----
Calib Index = 6
Calibration = 25mm, Empty, 10C - 90C
-----
Calib Index = 7
Calibration = 25mm, Empty, 150C - 350C
-----
Calib Index = 8
Calibration = 25mm, Empty, 35C - 150C
-----
Calib Index = 9
Calibration = 25mm, Empty, 80C - 200C
-----
Calib Index = 10
Calibration = 50mm, Empty, -20C - 55C
-----
Calib Index = 11
Calibration = 50mm, Empty, 10C - 90C
Version 1 – En Page 8
-----
Calib Index = 12
Calibration = 50mm, Empty, 150C - 350C
-----
Calib Index = 13
Calibration = 50mm, Empty, 35C - 150C
-----
Calib Index = 14
Calibration = 50mm, Empty, 80C - 200C
-----
Calib Index = 15
Calibration = 50mm, ND2, 250C - 600C
-----
Calib Index = 16
Calibration = 50mm, ND2, 500C - 1200C
-----
Calib Index = 17
Calibration = 50mm, ND2, 850C - 2000C
-----
Version 1 – En Page 9
Loading a factory calibration in a preset
Once you have obtained details on the calibration files and know which one you want to load in
which preset, follow these two steps:
The code below loads the calibration file “50mm, Empty, 35C - 150C”, having index 13 in the list
of the previous section, into Preset0.
#Loading a calibration
Calibration_to_load ='50mm, Empty, 35C - 150C'
CalibrationTag_node = PySpin.CStringPtr(nodemap.GetNode('PS0CalibrationLoadTag'))
CalibrationTag_node.SetValue(Calibration_to_load)
CalibrationActive_node = PySpin.CCommandPtr(nodemap.GetNode('PS0CalibrationLoad'))
CalibrationActive_node.Execute()
Note that loading a factory calibration also loads the corresponding factory correction. The camera
may also undergo a shutter maneuver.
Version 1 – En Page 10
Extracting the maximum and minimum count values for the current factory
calibration
We assume here that a factory calibration is loaded.
Version 1 – En Page 11
Extracting the Clock Value
The clock value is the base time step considered for the camera. Most time-based parameters like
integration time, framerate and superframe rates, etc. can be expressed as a multiple of clock
values.
Version 1 – En Page 12
Activating Single preset
There are several solutions for Single preset.
Either there is a factory calibration that is loaded in the desired preset. Or there is no factory
calibration, and the integration time is manually set. In the first case, TempLinear mode can be
activated on top. In the second case, streaming is only in counts.
Version 1 – En Page 13
Getting/Setting the frame rate of a preset
Alternately, when in Single preset mode, one can also use the node PS0FrameRate instead of
PS0FrameRateActual.
Version 1 – En Page 14
Activating Superframing mode
The examples below show some solutions, but not all of them. Possible values of registers are found
in the GenICamICD document.
We assume that the proper factory calibrations are loaded in the desired presets.
#Activating PS0 and PS1 for Superframing, PS2 and PS3 are not activated
node_PS0_For_Superframing =
PySpin.CBooleanPtr(nodemap.GetNode('PS0SubframeEnabled'))
node_PS1_For_Superframing =
PySpin.CBooleanPtr(nodemap.GetNode('PS1SubframeEnabled'))
node_PS2_For_Superframing =
PySpin.CBooleanPtr(nodemap.GetNode('PS2SubframeEnabled'))
node_PS3_For_Superframing =
PySpin.CBooleanPtr(nodemap.GetNode('PS3SubframeEnabled'))
node_PS0_For_Superframing.SetValue(True)
node_PS1_For_Superframing.SetValue(True)
node_PS2_For_Superframing.SetValue(False)
node_PS3_For_Superframing.SetValue(False)
#Defining the SuperFrame period (in clocks), Example for 40 ms (or 25 Hz)
#For X-series Base Clock = 1.01759 E-6 ms
Superframe_Width = 444000
SuperframeWidth_node = PySpin.CIntegerPtr(nodemap.GetNode('SuperframeWidth'))
SuperframeWidth_node.SetValue(Superframe_Width)
Version 1 – En Page 15
Preparing Preset Sequencing
Preparing Preset Sequencing means for each preset:
Loading a calibration file (or the integration time in case there is no need for a calibration)
Defining the framerate
Defining the dwell count
The maximum framerate depends on the integration time. Therefore, the operator must verify first
what its value is using the node PSxFrameRateMax.
Methods for loading a calibration file and defining the framerate are described in previous sections.
Here are the details for the dwell count. Example is given for Preset 0; change numbering for the
other presets. Note that inactivating a preset is obtained by setting a dwell count to zero.
Version 1 – En Page 16
Activating Preset Sequencing mode
We assume here that the proper factory calibrations are loaded in the desired presets, and the
sequence is already prepared.
Version 1 – En Page 17
Getting/Setting the object parameters
Setting the object parameters is important when the temperature linear mode is implemented. The
conversion from counts to temperature is then performed in the camera head.
Node Description
ObjectEmissivity Emissivity of the target (varies between 0 and 1)
ObjectDistance Distance to target (in meters)
ReflectedTemperature Reflected apparent temperature (in kelvins)
AtmosphericTemperature Average atmospheric temperature along the optical path (in
kelvins)
ExtOpticsTemperature External optics temperature (in kelvins)
ExtOpticsTransmission External optics transmission coefficient (varies between 0 and 1)
EstimatedTransmission Estimated atmospheric transmission coefficient (varies between 0
and 1). If not possible to set, then value 1.0 is used.
RelativeHumidity Average relative humidity along the optical path (varies between 0
and 1)
When the estimated transmission is set to 0, the value that is effectively considered is calculated
from the object parameters with a mathematic model. It is replaced by a fixed value if one wants to
override the estimation.
Version 1 – En Page 18
Setting the Temperature Linear mode
When the temperature linear mode is activated, the digital output is proportional to the
temperature in kelvins.
Res (resolution) is 0.1 for TempLinear100mK and 0.01 for TempLinear10mK. Object parameters are
those contained in the camera memory, and they are applied at once to all pixels.
The output is set to 16 bits and the obtained ranges are therefore:
#For Niceville cooled cameras in Temp Linear Mode (only A-series as not implemented
on X-series)
node_temp_linear = PySpin.CEnumerationPtr(nodemap.GetNode('IRFormat'))
node_temp_linear_low =
PySpin.CEnumEntryPtr(node_temp_linear.GetEntryByName('TemperatureLinear100mK'))
linear_low = node_temp_linear_low.GetValue()
node_temp_linear.SetIntValue(linear_low)
Version 1 – En Page 19
Retrieving the calibration coefficients, and obtaining radiance and temperature
images for a blackbody
We assume that a given factory calibration has been selected before and is active. Also, the
temperature linear mode is either not implemented or the operator does not want to use it.
# Retrieving Calibration constants
CalibrationQueryCoeff0_node =
PySpin.CFloatPtr(nodemap.GetNode('CalibrationQueryCoeff0'))
CalibrationQueryCoeff0 = CalibrationQueryCoeff0_node.GetValue()
CalibrationQueryCoeff1_node =
PySpin.CFloatPtr(nodemap.GetNode('CalibrationQueryCoeff1'))
CalibrationQueryCoeff1 = CalibrationQueryCoeff1_node.GetValue()
CalibrationQueryCoeff2_node =
PySpin.CFloatPtr(nodemap.GetNode('CalibrationQueryCoeff2'))
CalibrationQueryCoeff2 = CalibrationQueryCoeff2_node.GetValue()
CalibrationQueryR_node =
PySpin.CFloatPtr(nodemap.GetNode('CalibrationQueryR'))
R = CalibrationQueryR_node.GetValue()
CalibrationQueryB_node =
PySpin.CFloatPtr(nodemap.GetNode('CalibrationQueryB'))
B = CalibrationQueryB_node.GetValue()
CalibrationQueryF_node =
PySpin.CFloatPtr(nodemap.GetNode('CalibrationQueryF'))
F = CalibrationQueryF_node.GetValue()
For a blackbody
If we get an array of count values called image_Counts, then the corresponding array in radiance
is obtained with the formula:
When a dual factory calibration (radiance and temperature) is achieved, the assumption is that the
system responds linearly in radiance. Therefore, Coeff2 is very small.
Version 1 – En Page 20
The calibration in temperature obeys datapoints fit with a modified monochromatic Planck’s
formula, elaborated in 1982 by a Japanese team lead by Fumihiro Sakuma. It is now referred to as
the RBF equation.
From the radiance array previously defined, the temperature array in degrees Celsius is obtained
with the formula:
Version 1 – En Page 21