Rotpy
Python bindings for the Spinnaker SDK to enable Pythonic control of Teledyne/FLIR/Point Grey USB and GigE cameras.
Install / Use
/learn @matham/RotpyREADME
RotPy
RotPy provides python bindings for the Spinnaker SDK to enable Pythonic control of Teledyne/FLIR/Point Grey USB and GigE cameras.
See the website <https://matham.github.io/rotpy/index.html>_ for the complete documentation.
.. image:: https://github.com/matham/rotpy/workflows/Python%20application/badge.svg :target: https://github.com/matham/rotpy/actions :alt: Github CI status
Installation
You can install RotPy using pre-compiled wheels on Windows, Linux, or Mac or by installing the Spinnaker SDK and then installing RotPy from source.
Either way, you'll likely need to install the Spinnaker drivers so that the cameras
are recognized. Please download it from their website <https://www.flir.com/products/spinnaker-sdk/>_
and follow the instructions to install the drivers if the cameras are not found.
Pre-compiled wheels
To install from the pre-compiled wheels (assuming it's available on your platform), simply do::
python -m pip install rotpy
.. note::
For Windows, if rotpy errors out saying dll not found, you probably need
to install the
`Microsoft Visual C++ Redistributable <https://docs.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist>`_
(`64-bit <https://aka.ms/vs/17/release/vc_redist.x64.exe>`_,
`32-bit <https://aka.ms/vs/17/release/vc_redist.x86.exe>`_).
.. warning::
RotPy is licensed under MIT. However, the pre-compiled wheels contain some of the
Spinnaker SDK runtime libraries which have their own license. Please see the
license file packaged along with the binaries in the wheel.
From source
To install RotPy from source, you need to:
#. Install the
Spinnaker SDK <https://www.flir.com/products/spinnaker-sdk/>_ development
libraries.
#. Install a C++ compiler that supports C++11. E.g. on Windows Visual Studio etc.
On Mac you may have to export the following environment variables::
export CXX="/usr/bin/clang"
export CXXFLAGS="-std=c++11"
export CPPFLAGS="-std=c++11"
#. Set the environment variables so Python can locate the Spinnaker SDK.
#. You need to set ROTPY_INCLUDE to the include directory, e.g. on Windows it may be something like
set ROTPY_INCLUDE="C:\Program Files\FLIR\Spinnaker\include". On Linux and Mac it should typically
be automatically found.
#. You need to set ROTPY_LIB to the paths that contain the libraries and binaries. E.g. on Windows it may
be set ROTPY_LIB="C:\Program Files\FLIR\Spinnaker\bin64\vs2015;C:\Program Files\FLIR\Spinnaker\lib64\vs2015".
On Linux and Mac, again, it should typically be automatically found.
#. Then install RotPy with::
python -m pip install rotpy --no-binary rotpy
#. At runtime, you'll need to ensure the Spinnaker runtime binaries are on the
system PATH using e.g.
os.add_dll_directory <https://docs.python.org/3/library/os.html#os.add_dll_directory>_.
You may also have to set the environmental variable (depending on the OS bitness)
GENICAM_GENTL32_PATH/GENICAM_GENTL64_PATH
to the directory containing the FLIR_GenTL*.cti file as well as any or all variables
FLIR_GENTL32_CTI_VS140/FLIR_GENTL64_CTI_VS140/FLIR_GENTL32_CTI/FLIR_GENTL64_CTI
to the full path to the FLIR_GenTL*.cti file.
Additionally, the FLIR_GenTL*.cti file containing directory may also need to be added
to the system PATH. Spinnaker will raise an error if the cti file cannot be loaded.
Examples
Getting an image from a GigE camera
.. code-block:: python
>>> from rotpy.system import SpinSystem
>>> from rotpy.camera import CameraList
>>> # get a system ref and a list of all attached cameras
>>> system = SpinSystem()
>>> cameras = CameraList.create_from_system(system, update_cams=True, update_interfaces=True)
>>> cameras.get_size()
1
>>> # get the camera attached from the list
>>> camera = cameras.create_camera_by_index(0)
>>> camera.get_unique_id()
'77T45WD4A84C_86TA1684_GGGGGG14_64CW3987'
>>> # init the camera and get one image
>>> camera.init_cam()
>>> # get its serial number
>>> camera.camera_nodes.DeviceSerialNumber.get_node_value()
'36548975'
>>> camera.begin_acquisition()
>>> image_cam = camera.get_next_image(timeout=5)
>>> # we copy the image so that we can release its camera buffer
>>> image = image_cam.deep_copy_image(image_cam)
>>> image_cam.release()
>>> camera.end_acquisition()
>>> # save the image
>>> image.save_png('image.png')
>>> # get image metadata
>>> image.get_bits_per_pixel()
8
>>> image.get_height()
512
>>> image.get_width()
612
>>> image.get_frame_id()
1
>>> image.get_frame_timestamp()
67557050882
>>> image.get_pix_fmt()
'Mono8'
>>> image.get_image_data_size()
313344
>>> data = image.get_image_data()
>>> type(data)
bytearray
>>> len(data)
313344
>>> 512 * 612
313344
>>> camera.deinit_cam()
>>> camera.release()
Configuring and getting an image from a USB3 camera
.. code-block:: python
>>> from rotpy.system import SpinSystem
>>> from rotpy.camera import CameraList
>>> # create system/camera list instance and create the camera by serial number
>>> system = SpinSystem()
>>> cameras = CameraList.create_from_system(system, True, True)
>>> cameras.get_size()
1
>>> camera = cameras.create_camera_by_serial('87785435')
>>> # init so we can read the pixel format node
>>> camera.init_cam()
>>> # the names of the pixel formats available for the camera
>>> camera.camera_nodes.PixelFormat.get_entries_names()
['Mono8',
'Mono12Packed',
'Mono12p',
'Mono16',
'BayerGR8',
...,
'BayerBG16',
'YCbCr411_8_CbYYCrYY',
'YCbCr422_8_CbYCrY',
'YCbCr8_CbYCr',
'RGB8']
>>> # the current one is BayerRG8
>>> node = camera.camera_nodes.PixelFormat.get_node_value()
>>> node
<rotpy.node.SpinEnumItemNode at 0x236edec43c8>
>>> node.get_enum_name()
'BayerRG8'
>>> # instead set it to RGB8
>>> camera.camera_nodes.PixelFormat.set_node_value_from_str('RGB8')
>>> camera.camera_nodes.PixelFormat.get_node_value().get_enum_name()
'RGB8'
>>> # set acquired image height to 800 pixels
>>> camera.camera_nodes.Height.get_node_value()
1200
>>> camera.camera_nodes.Height.set_node_value(800)
>>> camera.camera_nodes.Height.get_node_value()
800
>>> camera.camera_nodes.Height.get_max_value()
1200
>>> # get the current framerate
>>> camera.camera_nodes.AcquisitionFrameRate.is_readable()
True
>>> camera.camera_nodes.AcquisitionFrameRate.get_node_value()
42.7807502746582
>>> # get one image and copy and release it so we don't tie up the buffers
>>> camera.begin_acquisition()
>>> image_cam = camera.get_next_image()
>>> image = image_cam.deep_copy_image(image_cam)
>>> image_cam.release()
>>> camera.end_acquisition()
>>> # get some image metadat
>>> image.get_frame_timestamp() / 1e9
512.51940629
>>> image.get_height()
800
>>> image.get_buffer_size()
4608000
>>> 1920*800*3
4608000
>>> image.get_pix_fmt()
'RGB8'
>>> # cleanup
>>> camera.deinit_cam()
>>> camera.release()
System and camera properties
The system and camera properties can be read and set using
node <https://matham.github.io/rotpy/node.html>_
objects. These nodes, each represent a camera or system property, and they
can be integer nodes, float nodes, boolean nodes, string nodes, command
nodes etc.
These nodes derive from Spinnaker's GenICam <https://en.wikipedia.org/wiki/GenICam>_
implementation for their cameras. RotPy provides access to a generic node access API
as well as to some pre-listed nodes available on many cameras.
The generic API is accessed through the NodeMap <https://matham.github.io/rotpy/node.html#rotpy.node.NodeMap>_ using
e.g. SpinSystem.get_tl_node_map <https://matham.github.io/rotpy/system.html#rotpy.system.SpinSystem.get_tl_node_map>,
InterfaceDevice.get_tl_node_map <https://matham.github.io/rotpy/system.html#rotpy.system.InterfaceDevice.get_tl_node_map>,
Camera.get_node_map <https://matham.github.io/rotpy/camera.html#rotpy.camera.Camera.get_node_map>,
Camera.get_tl_dev_node_map <https://matham.github.io/rotpy/camera.html#rotpy.camera.Camera.get_tl_dev_node_map>, or
Camera.get_tl_stream_node_map <https://matham.github.io/rotpy/camera.html#rotpy.camera.Camera.get_tl_stream_node_map>_.
The pre-listed nodes can be accessed through e.g.
SpinSystem.system_nodes <https://matham.github.io/rotpy/system.html#rotpy.system.SpinSystem.system_nodes>,
InterfaceDevice.interface_nodes <https://matham.github.io/rotpy/system.html#rotpy.system.InterfaceDevice.interface_nodes>,
Camera.camera_nodes <https://matham.github.io/rotpy/camera.html#rotpy.camera.Camera.camera_nodes>,
Camera.tl_dev_nodes <https://matham.github.io/rotpy/camera.html#rotpy.camera.Camera.tl_dev_nodes>, or
Camera.tl_stream_nodes <https://matham.github.io/rotpy/camera.html#rotpy.camera.Camera.tl_stream_nodes>.
These link to the following respective
objects: SystemNodes <https://matham.github.io/rotpy/system_nodes.html#rotpy.system_nodes.SystemNodes>,
InterfaceNodes <https://matham.github.io/rotpy/system_nodes.html#rotpy.system_nodes.InterfaceNodes>,
CameraNodes <https://matham.github.io/rotpy/camera_nodes.html#rotpy.camera_nodes.CameraNodes>,
TLDevNodes <https://matham.github.io/rotpy/camera_nodes.html#rotpy.camera_nodes.TLDevNodes>_, and
`TLStreamNodes https://matham.github.io/rotpy/camera_nodes.html#rotpy.camera_nodes.TLStreamNodes
