Camera API reference

Contents

Camera API reference#

class pyflir.Camera(ip: str | None = None, interface_ip: str | None = None, timeout: float = 2.0)[source]#

Bases: object

FLIR GigE Vision camera controller.

Uses pyGigEVision for GVCP control and GVSP image streaming. Vendor-specific registers are accessed directly via addresses in pyflir.registers.

Parameters:
  • ip – Camera IP address. None = auto-discover first camera.

  • interface_ip – Local NIC IP for discovery and streaming. Useful with multiple network interfaces.

  • timeout – GVCP socket timeout in seconds.

Examples:

with Camera() as cam:
    cam.download_xml()
    cam.load_xml("camera_xxx.xml")
    cam.start_stream()
    frame = cam.read()
    cam.stop_stream()

# Single-shot grab
with Camera() as cam:
    cam.load_xml("camera_xxx.xml")
    frame = cam.grab()
connect() None[source]#

Discover (if needed), open GVCP connection, and acquire control.

Raises:

CameraError – If no camera is found or the connection fails.

disconnect() None[source]#

Stop streaming (if active), release CCP control, close sockets.

property is_connected: bool#

Whether the camera GVCP session is active.

property is_streaming: bool#

Whether GVSP streaming is currently active.

property resolution: tuple[int, int]#

Current image resolution as (width, height) in pixels.

download_xml(save_path: str | None = None) bytes[source]#

Download the GenICam XML from the camera and save it to disk.

Uses pyGigEVision to fetch and decompress the descriptor stored in the camera’s on-board memory (bootstrap register 0x0200).

Parameters:

save_path – Output file path. Defaults to camera_<serial>.xml.

Returns:

Raw XML bytes.

load_xml(xml_path: str) None[source]#

Load and parse a previously saved GenICam XML file.

After loading, width/height are read from the camera registers and feature aliases are built for SFNC compatibility.

Parameters:

xml_path – Path to the GenICam XML file.

start_stream(packet_size: int = 1500, packet_delay: int = 0) None[source]#

Configure stream channel 0 and send AcquisitionStart.

Parameters:
  • packet_size – GVSP packet size in bytes (≤1500 for standard Ethernet; up to 9000 for jumbo frames if both ends support it).

  • packet_delay – Inter-packet delay in timestamp ticks. 0 = max speed.

Raises:

CameraError – If not connected or image dimensions are unknown.

stop_stream() None[source]#

Send AcquisitionStop and shut down the GVSP receiver.

grab(timeout: float = 5.0) ndarray[source]#

Start streaming, capture one frame, stop streaming, and return it.

Convenience for single-shot capture. XML must be loaded first.

Parameters:

timeout – Seconds to wait for a frame.

Returns:

2D numpy array (H, W), dtype uint16.

read(timeout: float = 5.0, latest: bool = False) ndarray[source]#

Return a frame from the live stream as a numpy array (H × W).

Parameters:
  • timeout – Seconds to wait for a frame before raising CameraError.

  • latest – If True, drain the queue and return only the most recent frame. Use in live-display loops to prevent lag from building up.

Returns:

2D numpy array (H, W), dtype uint16.

Raises:

CameraError – If not streaming or no frame arrives in time.

acquire(n_frames: int, timeout: float = 30.0) list[ndarray][source]#

Capture exactly n_frames frames and return them as a list.

If streaming is already active, reads from the live stream. Otherwise starts it automatically, captures, then stops:

frames = cam.acquire(50)   # no start_stream() / stop_stream() needed
Parameters:
  • n_frames – Number of frames to capture.

  • timeout – Total seconds to wait before raising CameraError.

Returns:

List of (H, W) numpy arrays, dtype uint16.

read_int(feature: str) int[source]#

Read an Integer register feature from the camera.

write_int(feature: str, value: int) None[source]#

Write an Integer register feature.

read_float(feature: str) float[source]#

Read a Float register feature (32-bit IEEE 754).

write_float(feature: str, value: float) None[source]#

Write a Float register feature.

execute_command(feature: str) None[source]#

Execute a Command register feature (e.g. AcquisitionStart).

read_enum(feature: str) str[source]#

Read an Enumeration feature and return the entry name.

write_enum(feature: str, entry_name: str) None[source]#

Write an Enumeration feature by entry name.

list_features() dict[str, RegNode][source]#

Return the full register map loaded from GenICam XML.

property frame_rate: float#

Acquisition frame rate in Hz.

property frame_rate_max: float | None#

Maximum frame rate for the current ROI (read-only, from camera).

property exposure_ms: float#

Integration time in milliseconds.

property detector_temperature: float#

Detector (FPA) temperature in degrees Celsius.

get_exposure() float[source]#

Return current integration time in seconds.

set_exposure(seconds: float) None[source]#

Set integration time in seconds.

get_frame_rate() float[source]#

Return current acquisition frame rate in Hz.

set_frame_rate(fps: float) None[source]#

Set acquisition frame rate in Hz.

get_width() int[source]#
set_width(pixels: int) None[source]#
get_height() int[source]#
set_height(pixels: int) None[source]#
get_temperature() float[source]#

Return detector temperature in degrees Celsius.

get_max_frame_rate() float | None[source]#

Return camera’s max frame rate for the current ROI, or None.

get_calibration_blocks() list[dict][source]#

Return a list of all calibration blocks with their temperature ranges.

Each entry has keys: index, name, lens, tmin, tmax. Temporarily iterates all blocks and restores the original selection.

get_calibration_block() int[source]#

Return the currently active calibration block index.

set_calibration_block(index: int) None[source]#

Select a calibration block (temperature range).

get_calibration(block: int | None = None) dict[source]#

Read calibration data for a calibration block.

If block is None the currently active block is used. The active block is restored after reading.

Temperature conversion uses two polynomials:

  1. counts → radiance: W = Σ counts_coeffs[i] · counts^i − counts_background

  2. radiance → temp °C: T_C = Σ temp_coeffs[i] · W^i

Both tmin/tmax and the temp polynomial output are in °C.

Returns:

block, tmin, tmax (°C), counts_order, counts_coeffs, counts_background, temp_order, temp_coeffs.

Return type:

dict with keys

counts_to_temperature(counts: ndarray, emissivity: float | None = None, refl_temp_c: float | None = None, atm_temp_c: float | None = None, tau: float = 1.0) ndarray[source]#

Convert a raw uint16 frame to temperature in degrees Celsius.

Reads calibration for the currently active block, then applies two polynomial steps:

  1. counts → radiance: W = Σ counts_coeffs[i] · counts^i − background

  2. radiance → °C: T_C = Σ temp_coeffs[i] · W^i

If emissivity, refl_temp_c, or atm_temp_c are omitted they default to the values previously set via set_object_params().

Parameters:
  • counts – 2-D uint16 array (H, W) from grab() or read().

  • emissivity – Object surface emissivity (0–1).

  • refl_temp_c – Reflected apparent temperature in °C.

  • atm_temp_c – Atmospheric temperature in °C.

  • tau – Atmospheric transmission (0–1). 1 = no atmosphere.

Returns:

Float64 array (H, W) with temperature in degrees Celsius.

Example:

frame = cam.grab()
temp  = cam.counts_to_temperature(frame)
print(f"Centre pixel: {temp[256, 320]:.1f} °C")
get_emissivity() float[source]#
set_emissivity(value: float) None[source]#
get_object_params() dict[source]#

Return radiometry object parameters as a dict.

set_object_params(emissivity: float | None = None, distance_m: float | None = None, atm_temp_k: float | None = None, refl_temp_k: float | None = None, humidity: float | None = None) None[source]#

Set radiometry object parameters (any subset).

get_roi() dict[source]#

Return current ROI as {width, height, offset_x, offset_y}.

height reflects the usable image rows only; any trailing metadata rows appended by the camera firmware are excluded.

get_roi_limits() dict[source]#

Return {width_min, width_inc, height_min, height_inc, sensor_width, sensor_height}.

All height values are in usable image rows (metadata rows excluded).

set_roi(width: int, height: int, offset_x: int = 0, offset_y: int = 0) None[source]#

Set the acquisition ROI. Stream must be stopped first.

Width and height are validated against the camera’s increment constraints before being written. After writing, the max frame rate register updates automatically.

Parameters:
  • width – ROI width in pixels (must be a multiple of WidthInc).

  • height – ROI height in pixels.

  • offset_x – Horizontal offset from left edge of sensor.

  • offset_y – Vertical offset from top edge of sensor.

trigger_nuc(preset: int = 0) None[source]#

Apply the stored NUC correction coefficients for the given preset.

Loads pre-computed correction data (PS0–PS3) into the active pipeline. Does not compute a new NUC; to do that, move the physical flag into the FOV, capture a flat-field frame, then save and re-apply.

Parameters:

preset – Preset index to correct (0–3). Default 0.

flag_move_in_fov() None[source]#

Move the internal NUC flag into the field of view.

Only available on cameras equipped with a physical shutter (e.g. FLIR A6751sc). Call before capturing a flat-field reference.

flag_move_stowed() None[source]#

Move the internal NUC flag out of the field of view.

get_temperatures() dict[str, float][source]#

Read all available on-board temperature sensors.

Returns a dict with keys FPA, Digitizer, PowerBoard, FrontPanel (degrees Celsius). The selector register is restored to its original value after reading.

info() dict[source]#

Return a dict of the camera’s current state.

Includes IP, model, serial, ROI, frame rate, exposure, calibration block, detector temperature, and streaming status.

live_view(colormap: str = 'inferno', scale: int = 2) None[source]#

Open a live thermal image viewer window.

Requires the ‘gui’ extra: pip install pyflir[gui]

XML must be loaded first (for width/height). If streaming is already active it will be stopped and restarted by the viewer.

Parameters:
  • colormap – Matplotlib colormap name (default “inferno”).

  • scale – Display upscale factor (default 2 = double size).

read_register(addr: int) int[source]#

Read a raw 32-bit register value.

write_register(addr: int, value: int) None[source]#

Write a raw 32-bit register value.

read_float_register(addr: int) float[source]#

Read a register as IEEE 754 float.

write_float_register(addr: int, value: float) None[source]#

Write a register as IEEE 754 float.

Module-level helpers#

pyflir.discover(interface_ip: str | None = None, timeout: float = 2.0) list[dict][source]#

Discover GigE Vision cameras on the network.

Parameters:
  • interface_ip – Bind to this local IP to target a specific NIC. Omit to broadcast on all interfaces.

  • timeout – Seconds to wait for discovery replies.

Returns:

ip, mac, spec_version, manufacturer, model, device_version, manufacturer_info, serial, user_name, interface_ip (the local NIC that received the reply).

Return type:

List of dicts with keys

Example:

import pyflir
cameras = pyflir.discover(interface_ip="169.254.100.1")
for cam in cameras:
    print(cam["manufacturer"], cam["model"], cam["ip"])
pyflir.force_ip(camera: dict, ip: str, mask: str, gateway: str | None = None) None[source]#

Assign a new IP to a discovered camera by MAC, via GVCP FORCEIP.

Re-homes a camera that is on the wrong subnet (or fell back to link-local) without changing host NIC configuration. The camera reboots its IP stack; re-run pyflir.discover() afterwards to see the new address.

Parameters:
  • camera (dict) – A camera dict from pyflir.discover() (must contain "mac").

  • ip (str) – New IPv4 address and subnet mask for the camera.

  • mask (str) – New IPv4 address and subnet mask for the camera.

  • gateway (str or None, optional) – Default gateway, or None for none.

Connection diagnostics#

pyflir.tune_connection(cam, probe_only: bool = True, read_nic_info: bool = False) ConnectionReport[source]#

Probe the host NIC and return connection recommendations.

FLIR cameras do not have an onboard memory buffer, so this function performs a read-only probe phase only: it inspects the host NIC carrying the camera link (speed, USB vs. PCIe, MTU) and returns recommended start_stream kwargs.

Parameters:
  • cam (Camera) – A connected FLIR camera.

  • probe_only (bool, optional) – Ignored (always True for pyFlir; kept for API parity with pyTelops). Reserved for a future live-stream sweep.

  • read_nic_info (bool, optional) – Read (never change) host NIC facts to annotate the report. Requires psutil. Default False.

Return type:

ConnectionReport

class pyflir.ConnectionReport(recommended: dict, probe: ConnectionStats | None = None, warnings: list[str] = <factory>)#

Bases: object

Result of tune_connection().

Fields are documented below; pass the report to apply() to write the recommended settings onto a connected camera.

apply(cam) dict[source]#

Store the recommended packet_size on cam for future streams.

Does not change any system or camera setting; records the recommendation as cam._recommended_packet_size.

probe: ConnectionStats | None = None#
recommended: dict#
warnings: list[str]#
class pyflir.ConnectionStats(max_packet_size: int | None = None, link_speed_mbps: int | None = None, adapter_name: str | None = None, is_usb_adapter: bool | None = None)#

Bases: object

Read-only facts gathered from a tune_connection() probe.

Populated by pyflir.connection.tune_connection() and returned inside ConnectionReport.

adapter_name: str | None = None#
is_usb_adapter: bool | None = None#
max_packet_size: int | None = None#

Errors#

exception pyflir.CameraError[source]#

Bases: Exception

Raised for high-level camera operation failures.

GenICam XML#

pyflir.parse_genicam_xml(xml_bytes: bytes) dict[str, RegNode][source]#

Parse a GenICam XML blob and return {feature_name: RegNode}.

Only features with a plain numeric <Address> tag are included. Features whose address is computed at runtime (via <pAddress>, IntSwissKnife, StructEntry, etc.) are silently skipped.

class pyflir.RegNode(name: str, node_type: str, address: int, length: int = 4, access: str = 'RW', endianness: str = 'Big', sign: str = 'Unsigned', cmd_value: int | None = None, enum_entries: dict[str, int]=<factory>, description: str = '')#

Bases: object

Describes one GenICam feature backed by a hardware register.

access: str = 'RW'#
cmd_value: int | None = None#
description: str = ''#
endianness: str = 'Big'#
length: int = 4#
sign: str = 'Unsigned'#
name: str#
node_type: str#
address: int#
enum_entries: dict[str, int]#

File I/O#

pyflir.read_ats(filepath: str) tuple[source]#

Read a FLIR ATS-US recording file (.ats).

Returns:

  • raw (np.ndarray, shape (N, H, W), dtype uint16)

  • metadata (ATSMetadata)

Examples

>>> from pyflir.io import read_ats
>>> raw, meta = read_ats("recording.ats")
>>> print(meta.camera_model, raw.shape)
pyflir.read_sfmov(filepath: str)[source]#

Read a FLIR SFMOV sequence file (.sfmov).

Requires pysfmov: pip install pyflir[io]

pyflir.read_sfmov_meta(filepath: str) dict[source]#

Read metadata from a FLIR SFMOV sequence file (.sfmov).

Requires pysfmov: pip install pyflir[io]

class pyflir.FLIRATSReader(filepath: str)#

Bases: object

Reader for FLIR ATS-US thermal recording files (.ats).

Parameters:
  • filepath (str) – Path to the .ats file.

  • read()) (Attributes (populated after calling)

  • -------------------------------------------

  • raw (np.ndarray, shape (N, H, W), dtype uint16) – Raw sensor counts for all N frames.

  • temperature_C (np.ndarray, shape (N, H, W), dtype float32, or None) – Temperature in °C using linear calibration from the embedded XML. None if calibration data is absent.

  • metadata (ATSMetadata) – All extracted metadata as a structured dataclass.

Examples

>>> reader = FLIRATSReader("recording.ats").read()
>>> print(reader.metadata)
>>> print(reader.raw.shape)          # (N, H, W)
>>> print(reader.temperature_C.shape)
FILE_MAGIC = b'FLIR ATS-US File'#
export_csv(idx: int = 0, unit: str = 'C', path: str | None = None) str[source]#

Save one frame as a CSV file. Returns the output path.

export_npy(path: str | None = None) str[source]#

Save all raw uint16 frames as a .npy file. Returns the output path.

export_tiff(unit: str = 'C', path: str | None = None) str[source]#

Save all frames as a multi-page float32 TIFF. Requires tifffile.

get_temperature(unit: str = 'C') ndarray[source]#

Return temperature array in the requested unit (C, K, or F).

read() FLIRATSReader[source]#

Parse the file and populate raw, temperature_C, and metadata. Returns self.

class pyflir.ATSMetadata(filepath: str = '', file_size_bytes: int = 0, camera_model: str | None = None, camera_part: str | None = None, lens: str | None = None, filter: str | None = None, width: int = 0, height: int = 0, n_frames: int = 0, frame_start_byte: int = 0, stride_bytes: int = 0, sync_row_bytes: int = 0, emissivity: float | None = None, distance: float | None = None, relative_humidity: float | None = None, reflected_temp: float | None = None, atmosphere_temp: float | None = None, ext_optics_temp: float | None = None, ext_optics_transmission: float | None = None, range_counts_min: float | None = None, range_counts_max: float | None = None, range_radiance_min: float | None = None, range_radiance_max: float | None = None, range_temperaturec_min: float | None = None, range_temperaturec_max: float | None = None, range_temperaturek_min: float | None = None, range_temperaturek_max: float | None = None, range_temperaturef_min: float | None = None, range_temperaturef_max: float | None = None, range_temperaturer_min: float | None = None, range_temperaturer_max: float | None = None, source_unit: str | None = None, temperature_type: str | None = None, apply_nuc: str | None = None, apply_bp: str | None = None, display_min_c: float | None = None, display_max_c: float | None = None, display_mode: str | None = None, scale_mode: str | None = None, segmentation_enabled: str | None = None)#

Bases: object

All metadata extracted from a FLIR ATS-US file.

All fields are optional (None when not present in the file). Use as_dict() to convert to a plain dictionary or str() for a formatted summary.

apply_bp: str | None = None#
apply_nuc: str | None = None#
as_dict() dict[source]#

Return all metadata as a plain dictionary.

atmosphere_temp: float | None = None#
camera_model: str | None = None#
camera_part: str | None = None#
display_max_c: float | None = None#
display_min_c: float | None = None#
display_mode: str | None = None#
distance: float | None = None#
emissivity: float | None = None#
ext_optics_temp: float | None = None#
ext_optics_transmission: float | None = None#
file_size_bytes: int = 0#
filepath: str = ''#
filter: str | None = None#
frame_start_byte: int = 0#
height: int = 0#
lens: str | None = None#
n_frames: int = 0#
range_counts_max: float | None = None#
range_counts_min: float | None = None#
range_radiance_max: float | None = None#
range_radiance_min: float | None = None#
range_temperaturec_max: float | None = None#
range_temperaturec_min: float | None = None#
range_temperaturef_max: float | None = None#
range_temperaturef_min: float | None = None#
range_temperaturek_max: float | None = None#
range_temperaturek_min: float | None = None#
range_temperaturer_max: float | None = None#
range_temperaturer_min: float | None = None#
reflected_temp: float | None = None#
relative_humidity: float | None = None#
scale_mode: str | None = None#
segmentation_enabled: str | None = None#
source_unit: str | None = None#
stride_bytes: int = 0#
sync_row_bytes: int = 0#
temperature_type: str | None = None#
width: int = 0#