### Main Execution: Initialize Camera Manager and Start Logging Source: https://context7.com/seekthermal/seekcamera-python/llms.txt This is the main execution block that initializes the SeekCameraManager, sets up the `ThermalLogger`, registers the event callback, and starts a loop to keep the script running until interrupted. It uses a `try-except` block to catch `KeyboardInterrupt` for graceful shutdown. ```python # Main execution with SeekCameraManager(SeekCameraIOType.USB) as manager: logger = ThermalLogger() manager.register_event_callback(on_event, logger) try: while True: sleep(1.0) except KeyboardInterrupt: print("Stopping...") ``` -------------------------------- ### Format Code with Black Source: https://github.com/seekthermal/seekcamera-python/blob/main/CONTRIBUTING.md Install and run the Black formatter to ensure code style compliance. ```text # Install black pip3 install black # Run black in the current directory black . ``` -------------------------------- ### Handle Camera Events and Setup Logging Source: https://context7.com/seekthermal/seekcamera-python/llms.txt This function handles camera connection and disconnection events. It configures the camera for thermography, sets up the CSV log file, and starts the capture session. Ensure `SeekCameraManagerEvent` is imported. ```python def on_event(camera, event_type, event_status, logger): """Handle camera events with logging setup.""" print(f"{event_type}: {camera.chipid}") if event_type == SeekCameraManagerEvent.CONNECT: # Configure for thermography camera.temperature_unit = SeekCameraTemperatureUnit.CELSIUS camera.scene_emissivity = 0.95 # Open log file filename = f"thermal_log_{camera.chipid}.csv" logger.file = open(filename, 'w') logger.frame_count = 0 # Start thermography capture camera.register_frame_available_callback(on_frame, logger) camera.capture_session_start(SeekCameraFrameFormat.THERMOGRAPHY_FLOAT) elif event_type == SeekCameraManagerEvent.DISCONNECT: camera.capture_session_stop() if logger.file: logger.file.close() print(f"Logged {logger.frame_count} frames") ``` -------------------------------- ### Capture and Process Camera Frames Source: https://context7.com/seekthermal/seekcamera-python/llms.txt Demonstrates starting a capture session with single or multiple formats and accessing various frame data types from the camera_frame object. ```python from seekcamera import SeekCameraFrameFormat import numpy as np def start_multi_format_capture(camera): """Start capture with multiple frame formats.""" # Single format camera.capture_session_start(SeekCameraFrameFormat.THERMOGRAPHY_FLOAT) # Multiple formats using bitwise OR formats = ( SeekCameraFrameFormat.COLOR_ARGB8888 | SeekCameraFrameFormat.THERMOGRAPHY_FLOAT | SeekCameraFrameFormat.GRAYSCALE ) camera.capture_session_start(formats) def process_all_formats(camera_frame): """Access different frame formats from a camera frame.""" # Corrected frame - least processed, uint16 corrected = camera_frame.corrected print(f"Corrected: {corrected.width}x{corrected.height}, dtype: {corrected.data.dtype}") # Pre-AGC frame - before automatic gain correction, uint16 pre_agc = camera_frame.pre_agc # Thermography float - temperature values in Celsius, float32 thermo_float = camera_frame.thermography_float temps = thermo_float.data # numpy array of temperatures print(f"Min temp: {np.min(temps):.1f}C, Max temp: {np.max(temps):.1f}C") # Thermography fixed 10.6 - temperature in U10.6 format, uint16 thermo_fixed = camera_frame.thermography_fixed_10_6 # Convert to Celsius: temp_celsius = value / 64.0 # Grayscale frame - after AGC processing, uint8 grayscale = camera_frame.grayscale # Color ARGB8888 - colorized frame, shape (h, w, 4), uint8 color_argb = camera_frame.color_argb8888 bgra_image = color_argb.data # Compatible with OpenCV # Color RGB565 - packed format, uint16 color_rgb565 = camera_frame.color_rgb565 # Color AYUV - YUV format, shape (h, w, 4), uint8 color_ayuv = camera_frame.color_ayuv # Color YUY2 - packed YUV, shape (h, w, 2), uint8 color_yuy2 = camera_frame.color_yuy2 return temps # Frame format flags for reference # SeekCameraFrameFormat.CORRECTED = 0x04 # SeekCameraFrameFormat.PRE_AGC = 0x08 # SeekCameraFrameFormat.THERMOGRAPHY_FLOAT = 0x10 # SeekCameraFrameFormat.THERMOGRAPHY_FIXED_10_6 = 0x20 # SeekCameraFrameFormat.GRAYSCALE = 0x40 # SeekCameraFrameFormat.COLOR_ARGB8888 = 0x80 # SeekCameraFrameFormat.COLOR_RGB565 = 0x100 # SeekCameraFrameFormat.COLOR_AYUV = 0x200 # SeekCameraFrameFormat.COLOR_YUY2 = 0x400 ``` -------------------------------- ### Complete Thermal Viewer Application with OpenCV Source: https://context7.com/seekthermal/seekcamera-python/llms.txt This application displays thermal images from a Seek Thermal camera using OpenCV. It utilizes threading for asynchronous frame callbacks and handles camera connection/disconnection events. Configure the camera's color palette and start the capture session. Press 'q' to quit or 's' to save a screenshot. ```python from threading import Condition import cv2 import numpy as np from seekcamera import ( SeekCameraIOType, SeekCameraColorPalette, SeekCameraManager, SeekCameraManagerEvent, SeekCameraFrameFormat, SeekCamera, SeekFrame, ) class ThermalViewer: """Thermal camera viewer with OpenCV display.""" def __init__(self): self.busy = False self.frame = None self.camera = None self.frame_condition = Condition() self.first_frame = True self.running = True def on_frame(camera, camera_frame, viewer): """Frame callback - notify main thread of new frame.""" with viewer.frame_condition: viewer.frame = camera_frame.color_argb8888 viewer.frame_condition.notify() def on_event(camera, event_type, event_status, viewer): """Event callback - handle camera connections.""" print(f"{event_type}: {camera.chipid}") if event_type == SeekCameraManagerEvent.CONNECT: if viewer.busy: return # Already have a camera viewer.busy = True viewer.camera = camera viewer.first_frame = True # Configure camera camera.color_palette = SeekCameraColorPalette.TYRIAN # Start capture camera.register_frame_available_callback(on_frame, viewer) camera.capture_session_start(SeekCameraFrameFormat.COLOR_ARGB8888) elif event_type == SeekCameraManagerEvent.DISCONNECT: if viewer.camera == camera: camera.capture_session_stop() viewer.camera = None viewer.frame = None viewer.busy = False elif event_type == SeekCameraManagerEvent.ERROR: print(f"Error: {event_status}") def main(): window_name = "Seek Thermal Camera" cv2.namedWindow(window_name, cv2.WINDOW_NORMAL) with SeekCameraManager(SeekCameraIOType.USB) as manager: viewer = ThermalViewer() manager.register_event_callback(on_event, viewer) while viewer.running: with viewer.frame_condition: if viewer.frame_condition.wait(0.15): # 150ms timeout img = viewer.frame.data if viewer.first_frame: h, w = img.shape[:2] cv2.resizeWindow(window_name, w * 2, h * 2) viewer.first_frame = False cv2.imshow(window_name, img) key = cv2.waitKey(1) if key == ord('q'): break if key == ord('s'): # Screenshot cv2.imwrite('thermal_capture.png', img) if not cv2.getWindowProperty(window_name, cv2.WND_PROP_VISIBLE): break cv2.destroyAllWindows() if __name__ == "__main__": main() ``` -------------------------------- ### Manage Camera Discovery and Frame Capture with SeekCameraManager Source: https://context7.com/seekthermal/seekcamera-python/llms.txt Demonstrates initializing the camera manager, handling connection events, and processing thermal frame data asynchronously. Requires the Seek Thermal SDK 4.x runtime and numpy. ```python from seekcamera import ( SeekCameraIOType, SeekCameraManager, SeekCameraManagerEvent, SeekCameraFrameFormat, ) def on_event(camera, event_type, event_status, user_data): """Handle camera connection/disconnection events.""" print(f"{event_type}: {camera.chipid}") if event_type == SeekCameraManagerEvent.CONNECT: # Camera connected - start capturing frames print(f"Camera connected: SN={camera.serial_number}, FW={camera.firmware_version}") camera.register_frame_available_callback(on_frame, user_data) camera.capture_session_start(SeekCameraFrameFormat.THERMOGRAPHY_FLOAT) elif event_type == SeekCameraManagerEvent.DISCONNECT: # Camera disconnected - stop capture session camera.capture_session_stop() elif event_type == SeekCameraManagerEvent.ERROR: print(f"Camera error: {event_status}") elif event_type == SeekCameraManagerEvent.READY_TO_PAIR: # Micro Core camera needs pairing camera.store_calibration_data(None) # Pair from sensor flash def on_frame(camera, camera_frame, user_data): """Process incoming thermal frames.""" frame = camera_frame.thermography_float print(f"Frame: {frame.width}x{frame.height}, data shape: {frame.data.shape}") # Create manager for USB cameras (use SeekCameraIOType.SPI for SPI cameras) # Use bitwise OR for multiple IO types: SeekCameraIOType.USB | SeekCameraIOType.SPI with SeekCameraManager(SeekCameraIOType.USB) as manager: manager.register_event_callback(on_event, {"app_data": "example"}) # Main loop - events are handled asynchronously import time while True: time.sleep(1.0) ``` -------------------------------- ### Create a Feature Branch Source: https://github.com/seekthermal/seekcamera-python/blob/main/CONTRIBUTING.md Initialize a new branch from the main branch for development. ```bash # Use main as the starting branch git checkout main # Create a branch git checkout -b feature-my-change ``` -------------------------------- ### Configure Seek Camera Settings Source: https://context7.com/seekthermal/seekcamera-python/llms.txt Use this function to set various camera parameters after establishing a connection. Settings are applied between frames, and some require an active capture session. ```python from seekcamera import ( SeekCameraColorPalette, SeekCameraAGCMode, SeekCameraShutterMode, SeekCameraTemperatureUnit, SeekCameraFilter, SeekCameraFilterState, SeekCameraLinearAGCLockMode, ) def configure_camera(camera): """Configure camera settings after connection.""" # Get camera identification print(f"Chip ID: {camera.chipid}") print(f"Serial Number: {camera.serial_number}") print(f"Core Part Number: {camera.core_part_number}") print(f"Firmware Version: {camera.firmware_version}") print(f"IO Type: {camera.io_type}") print(f"IO Properties: {camera.io_properties}") # Set color palette for display frames camera.color_palette = SeekCameraColorPalette.TYRIAN # Options: WHITE_HOT, BLACK_HOT, SPECTRA, PRISM, TYRIAN, IRON, AMBER, HI, GREEN # Configure AGC mode camera.agc_mode = SeekCameraAGCMode.HISTEQ # or SeekCameraAGCMode.LINEAR # Configure Linear AGC settings camera.linear_agc_lock_mode = SeekCameraLinearAGCLockMode.AUTO # For manual mode: set lock_min and lock_max # camera.linear_agc_lock_mode = SeekCameraLinearAGCLockMode.MANUAL # camera.linear_agc_lock_min = 0.0 # camera.linear_agc_lock_max = 100.0 # Configure HistEQ AGC settings camera.histeq_agc_plateau = 0.1 # Plateau percentage camera.histeq_agc_gain_limit = 2.0 # Gain limit value camera.histeq_agc_alpha_time = 0.5 # Alpha time in seconds # Set temperature unit camera.temperature_unit = SeekCameraTemperatureUnit.CELSIUS # Options: CELSIUS, FAHRENHEIT, KELVIN # Set scene emissivity (0.0 to 1.0) camera.scene_emissivity = 0.95 # Set thermography offset (applied to all pixels) camera.thermography_offset = 0.0 # Get/set thermography window x, y, w, h = camera.thermography_window print(f"Thermography window: ({x}, {y}) {w}x{h}") camera.thermography_window = (0, 0, 206, 156) # Set custom window # Configure shutter mode (Mosaic Cores only) camera.shutter_mode = SeekCameraShutterMode.AUTO # For manual: camera.shutter_mode = SeekCameraShutterMode.MANUAL # Then trigger manually: camera.shutter_trigger() # Configure image processing filters camera.set_filter_state(SeekCameraFilter.GRADIENT_CORRECTION, SeekCameraFilterState.ENABLED) camera.set_filter_state(SeekCameraFilter.FLAT_SCENE_CORRECTION, SeekCameraFilterState.ENABLED) camera.set_filter_state(SeekCameraFilter.SHARPEN_CORRECTION, SeekCameraFilterState.ENABLED) # Get filter state state = camera.get_filter_state(SeekCameraFilter.GRADIENT_CORRECTION) print(f"Gradient correction: {state}") ``` -------------------------------- ### Create and Apply Custom Color Palette Source: https://context7.com/seekthermal/seekcamera-python/llms.txt Defines a custom color palette with a gradient from blue to red and applies it to the camera. Ensure the SeekCameraColorPaletteData and SeekCameraColorPalette classes are imported. ```python from seekcamera import SeekCameraColorPalette, SeekCameraColorPaletteData def create_custom_palette(camera): """Create and apply a custom color palette.""" # Create custom palette data with 256 BGRA entries # Each entry is (blue, green, red, alpha) palette_data = SeekCameraColorPaletteData() # Create a gradient from blue (cold) to red (hot) for i in range(256): # Linear interpolation: blue -> cyan -> green -> yellow -> red if i < 64: # Blue to cyan b, g, r = 255, i * 4, 0 elif i < 128: # Cyan to green b, g, r = 255 - (i - 64) * 4, 255, 0 elif i < 192: # Green to yellow b, g, r = 0, 255, (i - 128) * 4 else: # Yellow to red b, g, r = 0, 255 - (i - 192) * 4, 255 palette_data[i] = (b, g, r, 255) # (blue, green, red, alpha) # Apply to USER_0 palette slot camera.set_color_palette_data(SeekCameraColorPalette.USER_0, palette_data) # Activate the custom palette camera.color_palette = SeekCameraColorPalette.USER_0 def rainbow_palette(): """Create a rainbow color palette.""" palette_data = SeekCameraColorPaletteData() for i in range(256): # HSV to RGB conversion for rainbow effect h = i / 256.0 * 360.0 s, v = 1.0, 1.0 c = v * s x = c * (1 - abs((h / 60.0) % 2 - 1)) m = v - c if h < 60: r, g, b = c, x, 0 elif h < 120: r, g, b = x, c, 0 elif h < 180: r, g, b = 0, c, x elif h < 240: r, g, b = 0, x, c elif h < 300: r, g, b = x, 0, c else: r, g, b = c, 0, x palette_data[i] = ( int((b + m) * 255), int((g + m) * 255), int((r + m) * 255), 255 ) return palette_data # Available palette slots: USER_0, USER_1, USER_2, USER_3, USER_4 # Built-in palettes: WHITE_HOT, BLACK_HOT, SPECTRA, PRISM, TYRIAN, IRON, AMBER, HI, GREEN ``` -------------------------------- ### Define Versioning Scheme Source: https://github.com/seekthermal/seekcamera-python/blob/main/CONTRIBUTING.md The project follows a three-digit semantic versioning format. ```text [major].[minor].[patch] ``` -------------------------------- ### Handle SeekCamera Exceptions Source: https://context7.com/seekthermal/seekcamera-python/llms.txt Use specific exception types to catch and respond to common camera operation failures. Ensure appropriate error handling is implemented for device communication, permissions, and state-related issues. ```python from seekcamera import ( SeekCameraManager, SeekCameraIOType, SeekCameraFrameFormat, ) from seekcamera.error import ( SeekCameraError, SeekCameraDeviceCommunicationError, SeekCameraInvalidParameterError, SeekCameraPermissionsError, SeekCameraNoDeviceError, SeekCameraDeviceBusyError, SeekCameraTimeoutError, SeekCameraNotSupportedError, SeekCameraNotPairedError, ) def safe_camera_operation(camera): """Demonstrate error handling for camera operations.""" try: # Start capture session camera.capture_session_start(SeekCameraFrameFormat.COLOR_ARGB8888) except SeekCameraDeviceCommunicationError: print("Error: Lost communication with camera") except SeekCameraInvalidParameterError: print("Error: Invalid parameter passed to SDK") except SeekCameraPermissionsError: print("Error: Permission denied - check USB permissions") # On Linux: add udev rules or run as root except SeekCameraDeviceBusyError: print("Error: Camera is busy - stop other capture sessions") except SeekCameraTimeoutError: print("Error: Operation timed out") except SeekCameraNotSupportedError: print("Error: Operation not supported on this camera model") except SeekCameraNotPairedError: print("Error: Camera not paired - call store_calibration_data()") except SeekCameraError as e: print(f"SDK Error: {type(e).__name__}") def safe_manager_creation(): """Create camera manager with error handling.""" try: manager = SeekCameraManager(SeekCameraIOType.USB) return manager except RuntimeError as e: if "Failed to load" in str(e): print("Error: Seek Thermal SDK not installed") print("Install SDK from: https://thermal.com") elif "runtime version is insufficient" in str(e): print("Error: SDK version too old - update Seek Thermal SDK") else: print(f"Error: {e}") return None # Error codes reference: # -1: Device communication error # -2: Invalid parameter # -3: Permissions error # -4: No device # -5: Device not found # -6: Device busy # -7: Timeout # -8: Overflow # -99: Other error # -103: Cannot perform request # -1001: Not paired ``` -------------------------------- ### Push Branch to Remote Source: https://github.com/seekthermal/seekcamera-python/blob/main/CONTRIBUTING.md Push the local feature branch to the remote repository. ```bash git push -u origin feature-my-change ``` -------------------------------- ### Analyze Temperature Data with Numpy Source: https://context7.com/seekthermal/seekcamera-python/llms.txt This function analyzes a numpy array of temperature data to find minimum, maximum, mean, standard deviation, and median temperatures. It also identifies the hotspot location and counts pixels above a specified threshold. Requires `numpy`. ```python def analyze_temperatures(temps): """Analyze temperature array for hotspots and statistics.""" results = { 'min': np.min(temps), 'max': np.max(temps), 'mean': np.mean(temps), 'std': np.std(temps), 'median': np.median(temps), } # Find hotspot location max_idx = np.unravel_index(np.argmax(temps), temps.shape) results['hotspot_y'], results['hotspot_x'] = max_idx # Temperature histogram hist, bins = np.histogram(temps, bins=50) results['histogram'] = (hist, bins) # Threshold detection (pixels above 30C for example) threshold = 30.0 hot_pixels = np.sum(temps > threshold) results['pixels_above_threshold'] = hot_pixels return results ``` -------------------------------- ### Analyze Thermal Frame Data Source: https://context7.com/seekthermal/seekcamera-python/llms.txt This snippet demonstrates how to access and analyze thermal frame data and metadata using the SeekFrame and SeekCameraFrameHeader classes. ```APIDOC ## Analyze Thermal Frame Data ### Description This function analyzes thermal frame data and metadata obtained from a SeekThermal camera. ### Method Python function call ### Endpoint N/A (Local function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **camera** (object) - The camera object. - **camera_frame** (SeekCameraFrame) - The frame object obtained from the camera. ### Request Example ```python import numpy as np def analyze_frame(camera, camera_frame): """Analyze thermal frame data and metadata.""" # Get thermography frame frame = camera_frame.thermography_float # Access frame properties print(f"Width: {frame.width}") print(f"Height: {frame.height}") print(f"Channels: {frame.channels}") print(f"Pixel depth: {frame.pixel_depth} bits") print(f"Data size: {frame.data_size} bytes") print(f"Is empty: {frame.is_empty}") # Access frame data as numpy array data = frame.data # Shape depends on format print(f"Data shape: {data.shape}, dtype: {data.dtype}") # Access frame header for metadata header = frame.header # Frame identification print(f"Timestamp (UTC ns): {header.timestamp_utc_ns}") print(f"Camera CID: {header.chipid}") print(f"Camera SN: {header.serial_number}") print(f"Camera CPN: {header.core_part_number}") print(f"Firmware: {header.firmware_version}") print(f"IO Type: {header.io_type}") print(f"FPA Frame Count: {header.fpa_frame_count}") # Environment data print(f"Environment Temperature: {header.environment_temperature:.1f}C") print(f"FPA Diode Count: {header.fpa_diode_count}") # Thermography statistics (coordinates and values) min_x, min_y, min_val = header.thermography_min max_x, max_y, max_val = header.thermography_max spot_x, spot_y, spot_val = header.thermography_spot print(f"Min: {min_val:.1f}C at ({min_x}, {min_y})") print(f"Max: {max_val:.1f}C at ({max_x}, {max_y})") print(f"Spot: {spot_val:.1f}C at ({spot_x}, {spot_y})") # AGC settings used print(f"AGC Mode: {header.agc_mode}") print(f"Linear AGC Min: {header.linear_agc_min}") print(f"Linear AGC Max: {header.linear_agc_max}") print(f"HistEQ Bins: {header.histeq_agc_num_bins}") print(f"HistEQ Bin Width: {header.histeq_agc_bin_width}") print(f"HistEQ Gain Limit Factor: {header.histeq_agc_gain_limit_factor}") # Filter states print(f"Gradient Correction: {header.gradient_correction_filter_state}") print(f"Flat Scene Correction: {header.flat_scene_correction_filter_state}") print(f"Sharpen Correction: {header.sharpen_correction_filter_state}") return data ``` ### Response #### Success Response (200) - **data** (numpy.ndarray) - The thermal frame data as a NumPy array. #### Response Example ``` Width: 640 Height: 512 Channels: 1 Pixel depth: 16 bits Data size: 655360 bytes Is empty: False Data shape: (512, 640), dtype: uint16 Timestamp (UTC ns): 1678886400123456789 Camera CID: 12345 Camera SN: SN123456789 Camera CPN: CPN987654321 Firmware: 1.2.3 IO Type: 0 FPA Frame Count: 100 Environment Temperature: 25.5C FPA Diode Count: 327680 Min: 20.1C at (100, 150) Max: 50.5C at (200, 250) Spot: 35.2C at (150, 200) AGC Mode: 1 Linear AGC Min: 0 Linear AGC Max: 1000 HistEQ Bins: 256 HistEQ Bin Width: 4 HistEQ Gain Limit Factor: 1.5 Gradient Correction: True Flat Scene Correction: False Sharpen Correction: True ``` ``` -------------------------------- ### Log Thermography Data to CSV Source: https://context7.com/seekthermal/seekcamera-python/llms.txt This function logs frame statistics and raw temperature data to a CSV file. It requires the `numpy` and `csv` libraries. Ensure the file is opened in write mode before calling this function. ```python from time import sleep import numpy as np import csv from seekcamera import ( SeekCameraIOType, SeekCameraManager, SeekCameraManagerEvent, SeekCameraFrameFormat, SeekCameraTemperatureUnit, ) class ThermalLogger: def __init__(self): self.file = None self.frame_count = 0 def on_frame(camera, camera_frame, logger): """Log thermography data to CSV.""" frame = camera_frame.thermography_float temps = frame.data header = frame.header # Log frame statistics print(f"Frame {logger.frame_count}: " f"Min={header.thermography_min[2]:.1f}C, " f"Max={header.thermography_max[2]:.1f}C, " f"Spot={header.thermography_spot[2]:.1f}C") # Save raw temperature data np.savetxt(logger.file, temps, fmt="%.2f", delimiter=",") logger.file.write("\n") # Separator between frames logger.frame_count += 1 ``` -------------------------------- ### Commit with DCO Sign-off Source: https://github.com/seekthermal/seekcamera-python/blob/main/CONTRIBUTING.md Use the -s flag to sign off commits as required by the Developer Certificate of Origin. ```text git commit -s ``` -------------------------------- ### Trigger Manual Shutter Source: https://context7.com/seekthermal/seekcamera-python/llms.txt Manually trigger the shutter for Mosaic Cores. Ensure the shutter mode is set to MANUAL before calling this function. ```python def trigger_shutter(camera): """Manually trigger shutter for Mosaic Cores.""" camera.shutter_mode = SeekCameraShutterMode.MANUAL camera.shutter_trigger() ``` -------------------------------- ### Analyze Thermal Frame Data and Metadata Source: https://context7.com/seekthermal/seekcamera-python/llms.txt Use this function to extract and print detailed information from a thermal frame, including dimensions, pixel depth, data size, and thermography statistics like min/max/spot temperatures. It also accesses camera identification and processing parameters. ```python import numpy as np def analyze_frame(camera, camera_frame): """Analyze thermal frame data and metadata.""" # Get thermography frame frame = camera_frame.thermography_float # Access frame properties print(f"Width: {frame.width}") print(f"Height: {frame.height}") print(f"Channels: {frame.channels}") print(f"Pixel depth: {frame.pixel_depth} bits") print(f"Data size: {frame.data_size} bytes") print(f"Is empty: {frame.is_empty}") # Access frame data as numpy array data = frame.data # Shape depends on format print(f"Data shape: {data.shape}, dtype: {data.dtype}") # Access frame header for metadata header = frame.header # Frame identification print(f"Timestamp (UTC ns): {header.timestamp_utc_ns}") print(f"Camera CID: {header.chipid}") print(f"Camera SN: {header.serial_number}") print(f"Camera CPN: {header.core_part_number}") print(f"Firmware: {header.firmware_version}") print(f"IO Type: {header.io_type}") print(f"FPA Frame Count: {header.fpa_frame_count}") # Environment data print(f"Environment Temperature: {header.environment_temperature:.1f}C") print(f"FPA Diode Count: {header.fpa_diode_count}") # Thermography statistics (coordinates and values) min_x, min_y, min_val = header.thermography_min max_x, max_y, max_val = header.thermography_max spot_x, spot_y, spot_val = header.thermography_spot print(f"Min: {min_val:.1f}C at ({min_x}, {min_y})") print(f"Max: {max_val:.1f}C at ({max_x}, {max_y})") print(f"Spot: {spot_val:.1f}C at ({spot_x}, {spot_y})") # AGC settings used print(f"AGC Mode: {header.agc_mode}") print(f"Linear AGC Min: {header.linear_agc_min}") print(f"Linear AGC Max: {header.linear_agc_max}") print(f"HistEQ Bins: {header.histeq_agc_num_bins}") print(f"HistEQ Bin Width: {header.histeq_agc_bin_width}") print(f"HistEQ Gain Limit Factor: {header.histeq_agc_gain_limit_factor}") # Filter states print(f"Gradient Correction: {header.gradient_correction_filter_state}") print(f"Flat Scene Correction: {header.flat_scene_correction_filter_state}") print(f"Sharpen Correction: {header.sharpen_correction_filter_state}") return data ``` -------------------------------- ### Lock Frame for Thread-Safe Access Source: https://context7.com/seekthermal/seekcamera-python/llms.txt This snippet shows how to lock a frame for thread-safe access outside of a callback context. ```APIDOC ## Lock Frame for Thread-Safe Access ### Description This function locks a SeekCameraFrame to enable thread-safe access to its data outside of the original callback context. It ensures that the frame data is not modified while being processed. ### Method Python function call ### Endpoint N/A (Local function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **camera_frame** (SeekCameraFrame) - The frame object to be locked and processed. ### Request Example ```python def lock_frame_for_processing(camera_frame): """Lock frame for thread-safe access outside callback.""" # Lock the frame to safely access outside callback context camera_frame.lock() try: frame = camera_frame.thermography_float # Process frame data... data = frame.data.copy() # Make a copy for later use finally: # Always unlock when done camera_frame.unlock() return data ``` ### Response #### Success Response (200) - **data** (numpy.ndarray) - A copy of the thermal frame data. #### Response Example ``` # Example output would be a numpy array representing the thermal data # e.g., array([[20.1, 20.5, ...], [21.0, 21.2, ...], ...], dtype=float32) ``` ``` -------------------------------- ### Lock Frame for Thread-Safe Access Source: https://context7.com/seekthermal/seekcamera-python/llms.txt This function demonstrates how to safely access frame data from a callback context by locking the frame before processing and unlocking it afterward. It ensures thread-safe access by making a copy of the data. ```python def lock_frame_for_processing(camera_frame): """Lock frame for thread-safe access outside callback.""" # Lock the frame to safely access outside callback context camera_frame.lock() try: frame = camera_frame.thermography_float # Process frame data... data = frame.data.copy() # Make a copy for later use finally: # Always unlock when done camera_frame.unlock() return data ``` -------------------------------- ### Update Feature Branch Source: https://github.com/seekthermal/seekcamera-python/blob/main/CONTRIBUTING.md Merge changes from the main branch into a feature branch using no-fast-forward merging. ```bash git pull git checkout feature-my-change git merge --no-ff origin/main ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.