Skip to content

Getting Started with Python

PySpin provides Python bindings for the Spinnaker SDK, enabling rapid prototyping, data science workflows, and scripting-based camera control.

Installation & Compatibility

Platform Python Architecture Notes
Windows 10/11 3.10, 3.12 x64 Full support
Ubuntu 20.04 3.8 x64, ARM64, ARMHF Full support
Ubuntu 22.04 3.10 x64, ARM64, ARMHF Full support
Ubuntu 24.04 3.12 x64, ARM64, ARMHF Full support
macOS 14 (Sonoma)+ 3.10, 3.12 x64, ARM64 Full support
# Install from SDK wheel (bundled with SDK installer)
pip install spinnaker_python-4.4.0.246-cp312-cp312-win_amd64.whl

# Optional but recommended
pip install numpy opencv-python

Version Pinning

The PySpin wheel is tightly coupled to the installed Spinnaker runtime version. Mismatched versions will raise ImportError or cause runtime crashes. Always install the wheel that ships with your SDK version.


Prerequisites

  • Spinnaker SDK installed (download)
  • Python 3.10 or later
  • PySpin package installed (included with the SDK installer or via pip install spinnaker-python)
  • A supported Teledyne camera connected via USB3 or GigE

Basic Acquisition Example

The canonical example is located at src/PySpin/Examples/Python3/Acquisition.py in the SDK. Below is the essential workflow:

import PySpin

def main():
    # Get the system singleton
    system = PySpin.System.GetInstance()

    # Retrieve camera list
    cam_list = system.GetCameras()

    # Get the first camera
    cam = cam_list.GetByIndex(0)

    # Initialize
    cam.Init()

    # Configure acquisition mode
    cam.AcquisitionMode.SetValue(PySpin.AcquisitionMode_Continuous)

    # Begin acquisition
    cam.BeginAcquisition()

    # Retrieve images
    for i in range(10):
        image = cam.GetNextImage(1000)

        if not image.IsIncomplete():
            print(f"Image {i}: {image.GetWidth()} x {image.GetHeight()}")

        # Release image
        image.Release()

    # Clean up
    cam.EndAcquisition()
    cam.DeInit()
    del cam
    cam_list.Clear()
    system.ReleaseInstance()

if __name__ == "__main__":
    main()

Key Concepts

QuickSpin Properties

PySpin supports QuickSpin for direct property access:

cam.ExposureTime.SetValue(10000.0)
exposure = cam.ExposureTime.GetValue()

GenICam Node Access

For advanced features, access the GenICam nodemap:

nodemap = cam.GetNodeMap()
node_acquisition_mode = PySpin.CEnumerationPtr(
    nodemap.GetNode("AcquisitionMode"))

NumPy Integration

Convert images to NumPy arrays for processing:

image_data = image.GetNDArray()  # Returns a NumPy array

Feature Snippets

Hardware Triggering

Configure the camera for asynchronous hardware triggering on GPIO Line 0 (rising edge):

import PySpin

nodemap = cam.GetNodeMap()

# Disable trigger mode first to configure source
node_trigger_mode = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerMode'))
node_trigger_mode_off = node_trigger_mode.GetEntryByName('Off')
node_trigger_mode.SetIntValue(node_trigger_mode_off.GetValue())

# Set trigger selector to FrameStart
node_trigger_selector = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerSelector'))
node_trigger_selector_framestart = node_trigger_selector.GetEntryByName('FrameStart')
node_trigger_selector.SetIntValue(node_trigger_selector_framestart.GetValue())

# Set trigger source to Line0 (hardware)
node_trigger_source = PySpin.CEnumerationPtr(nodemap.GetNode('TriggerSource'))
node_trigger_source_line0 = node_trigger_source.GetEntryByName('Line0')
node_trigger_source.SetIntValue(node_trigger_source_line0.GetValue())

# Enable trigger mode
node_trigger_mode_on = node_trigger_mode.GetEntryByName('On')
node_trigger_mode.SetIntValue(node_trigger_mode_on.GetValue())

Setting Exposure Time

Set exposure to 20 milliseconds (20000 microseconds) using the QuickSpin API:

# Turn off auto exposure
cam.ExposureAuto.SetValue(PySpin.ExposureAuto_Off)

# Set exposure time in microseconds
cam.ExposureTime.SetValue(20000.0)

Setting Gain

Adjust analog gain using the QuickSpin API:

# Turn off auto gain
cam.GainAuto.SetValue(PySpin.GainAuto_Off)

# Set gain to 10.5 dB
cam.Gain.SetValue(10.5)

Event Handling

Handle device arrival and removal events using event handler classes:

import PySpin

class InterfaceEventHandler(PySpin.InterfaceEventHandler):
    def OnDeviceArrival(self, camera):
        print('Device arrived: serial %s' % camera.TLDevice.DeviceSerialNumber.GetValue())

    def OnDeviceRemoval(self, camera):
        print('Device removed')

# Register the handler on a system interface
handler = InterfaceEventHandler()
interface = system.GetInterfaces()[0]
interface.RegisterEventHandler(handler)

Chunk Data

Chunk data appends metadata such as frame counter, exposure time, and image dimensions to each acquired image:

nodemap = cam.GetNodeMap()

# Activate chunk mode
chunk_mode_active = PySpin.CBooleanPtr(nodemap.GetNode('ChunkModeActive'))
if PySpin.IsWritable(chunk_mode_active):
    chunk_mode_active.SetValue(True)

# Enable a specific chunk (e.g., ExposureTime)
chunk_selector = PySpin.CEnumerationPtr(nodemap.GetNode('ChunkSelector'))
entry = chunk_selector.GetEntryByName('ExposureTime')
chunk_selector.SetIntValue(entry.GetValue())

chunk_enable = PySpin.CBooleanPtr(nodemap.GetNode('ChunkEnable'))
if PySpin.IsWritable(chunk_enable):
    chunk_enable.SetValue(True)

# Retrieve chunk data from a grabbed image
chunk_data = image.GetChunkData()
exposure = chunk_data.GetExposureTime()

Error Handling

Use PySpin.SpinnakerException to catch SDK errors:

try:
    cam.Init()
except PySpin.SpinnakerException as ex:
    print('Error: %s' % ex)

Design Conventions

Context Manager Pattern

Always use with blocks or explicit cleanup — PySpin wraps native C++ handles and the GC cannot guarantee timely release:

import PySpin

system = PySpin.System.GetInstance()
cam_list = system.GetCameras()

try:
    for cam in cam_list:
        cam.Init()
        try:
            # ... configure and acquire ...
            pass
        finally:
            cam.DeInit()
            del cam
finally:
    cam_list.Clear()
    system.ReleaseInstance()

Do not rely on garbage collection

PySpin objects wrap native handles. Always call .DeInit(), .Clear(), and .ReleaseInstance() explicitly. Relying on del or GC to clean up camera handles will cause resource leaks and may hang subsequent sessions.

QuickSpin Property Access

QuickSpin exposes camera settings as typed Python properties — prefer this over raw node map access for common parameters:

# Raw node map access (verbose)
node_map = cam.GetNodeMap()
node = PySpin.CEnumerationPtr(node_map.GetNode("ExposureMode"))
node.SetIntValue(node.GetEntryByName("Timed").GetValue())

# QuickSpin equivalent (preferred)
cam.ExposureMode.SetValue(PySpin.ExposureMode_Timed)
cam.ExposureAuto.SetValue(PySpin.ExposureAuto_Off)
cam.ExposureTime.SetValue(5000.0)  # microseconds

NumPy Integration

PySpin.Image provides direct NumPy array access without copying:

image_result = cam.GetNextImage(1000)

if not image_result.IsIncomplete():
    # Convert and get as NumPy array
    converted = image_result.Convert(
        PySpin.PixelFormat_Mono8,
        PySpin.HQ_LINEAR
    )
    arr = converted.GetNDArray()   # shape: (H, W) or (H, W, C)

    # Optional: use with OpenCV
    import cv2
    cv2.imwrite("frame.png", arr)

image_result.Release()

Pixel Format Compatibility

NumPy access via GetNDArray() requires conversion to an unpacked format first (Mono8, RGB8, BGR8). Packed formats like BayerRG12p will raise a SpinnakerException.

Error Handling

PySpin raises PySpin.SpinnakerException on failure — wrap acquisition loops accordingly:

try:
    cam.BeginAcquisition()
except PySpin.SpinnakerException as ex:
    print(f"Acquisition failed: {ex}")
    raise

Quick Reference

System & Discovery

Class / Function Description
PySpin.System.GetInstance() Obtain the system singleton
PySpin.System.ReleaseInstance() Release the system singleton
PySpin.System.GetCameras() Enumerate connected cameras
PySpin.System.GetLibraryVersion() Query SDK version at runtime

Camera Lifecycle

Method Description
Camera.Init() Initialize the camera
Camera.DeInit() De-initialize and release the camera
Camera.BeginAcquisition() Start image acquisition
Camera.EndAcquisition() Stop image acquisition
Camera.GetNextImage(timeout) Retrieve next image with timeout (ms)

Image Handling

Method Description
Image.IsIncomplete() Check for incomplete transfer
Image.GetNDArray() Get image data as NumPy array
Image.GetData() Get raw byte buffer
Image.GetWidth() Image width in pixels
Image.GetHeight() Image height in pixels
Image.GetPixelFormat() Current pixel format enum
Image.Convert(format, algorithm) Convert to a different pixel format
Image.Release() Return image to acquisition buffer pool

Node Map & Configuration

Method Description
Camera.GetNodeMap() Access GenICam node map
Camera.GetTLDeviceNodeMap() Access transport layer device node map
Camera.GetTLStreamNodeMap() Access transport layer stream node map
INodeMap.GetNode(name) Retrieve a node by name
CIntegerPtr.GetValue() Read an integer node
CIntegerPtr.SetValue(val) Write an integer node
CEnumerationPtr.SetIntValue(val) Set an enumeration node

Events & Callbacks

Class Description
ImageEventHandler Base class for image arrival callbacks
DeviceEventHandler Base class for device events (e.g. exposure end)
LoggingEventHandler Base class for SDK log message callbacks
Camera.RegisterEventHandler() Attach an event handler to a camera
Camera.UnregisterEventHandler() Detach an event handler
class MyImageHandler(PySpin.ImageEventHandler):
    def OnImageEvent(self, image):
        arr = image.GetNDArray()
        print(f"Frame received: {arr.shape}")

handler = MyImageHandler()
cam.RegisterEventHandler(handler)
cam.BeginAcquisition()
# ... handler fires on each frame arrival ...
cam.EndAcquisition()
cam.UnregisterEventHandler(handler)

Exception Reference

PySpin raises PySpin.SpinnakerException on failure. The exception exposes the same SDK error details as the underlying C++ layer:

Attribute Description
str(ex) Human-readable error message
errorcode Numeric SDK error code (spinError)
filename Source file where the error originated
functionname Function name where the error originated
linenumber Line number where the error originated
fullmessage Concatenated full error details
try:
    cam.BeginAcquisition()
except PySpin.SpinnakerException as ex:
    print(f"Error {ex.errorcode}: {ex}")

Common error codes are listed in the C API Error Code Reference.


Known Issues & Limitations

SWIG Wrapper Overhead

PySpin is a SWIG-generated wrapper. High-frequency calls into the SDK (e.g. reading node values in a tight acquisition loop) incur per-call marshalling overhead. Move node lookups outside acquisition loops and cache node pointers where possible.

    # Bad — node lookup on every frame
    while acquiring:
        gain = cam.GetNodeMap().GetNode("Gain")

    # Good — cache outside the loop
    gain_node = PySpin.CFloatPtr(cam.GetNodeMap().GetNode("Gain"))
    while acquiring:
        val = gain_node.GetValue()

NumPy Array Lifetime

Arrays returned by GetNDArray() reference SDK-managed memory. If you need to retain the data after calling Image.Release(), copy the array explicitly:

    arr = image.GetNDArray().copy()  # detach from SDK buffer
    image.Release()
    # arr is now safe to use after release

Further Reading