Quick Start Guide
This guide will help you get started with PyThermal quickly.
Unified Capture Interface
The ThermalCapture class provides a unified interface for both live camera feeds and recorded sequences. It’s similar to cv2.VideoCapture and automatically handles device initialization:
from pythermal import ThermalCapture
# For live camera (default - uses smallest available device)
capture = ThermalCapture() # or ThermalCapture(0) or ThermalCapture(None)
# For specific device (by consistent device ID)
capture = ThermalCapture(device_index=1) # Use device with ID 1
# For recorded sequence
capture = ThermalCapture("recordings/thermal_20240101.tseq")
# Check for new frame
if capture.has_new_frame():
# Get metadata
metadata = capture.get_metadata()
print(f"Frame {metadata.seq}: {metadata.min_temp:.1f}°C - {metadata.max_temp:.1f}°C")
# Get YUYV frame (240x240)
yuyv_frame = capture.get_yuyv_frame()
# Get temperature array (96x96, uint16)
temp_array = capture.get_temperature_array()
# Mark frame as read
capture.mark_frame_read()
# Cleanup
capture.release()
Or use as a context manager:
with ThermalCapture() as capture:
if capture.has_new_frame():
metadata = capture.get_metadata()
yuyv_frame = capture.get_yuyv_frame()
temp_array = capture.get_temperature_array()
capture.mark_frame_read()
# Automatically releases on exit
Live View
Display real-time thermal imaging feed or replay recorded sequences:
Basic Usage
from pythermal import ThermalLiveView
# Live camera view
viewer = ThermalLiveView()
viewer.run() # Opens OpenCV window with live thermal feed
# Or replay a recorded file
viewer = ThermalLiveView(source="recordings/thermal_20240101.tseq")
viewer.run()
Enhanced Live View with Multiple View Modes
The example live_view.py demonstrates an enhanced live view with multiple display modes:
from pythermal import ThermalLiveView
from pythermal.utils import estimate_environment_temperature_v1
class EnhancedLiveView(ThermalLiveView):
"""Enhanced live view with additional color modes"""
def __init__(self, source=None):
super().__init__(source)
# View modes: 'yuyv', 'temperature', 'temperature_celsius'
self.view_modes = ['yuyv', 'temperature', 'temperature_celsius']
self.view_mode_index = 0
self.view_mode = self.view_modes[self.view_mode_index]
self.clahe_contrast = 3.0 # Contrast enhancement level
def toggle_view_mode(self):
"""Toggle to next view mode"""
self.view_mode_index = (self.view_mode_index + 1) % len(self.view_modes)
self.view_mode = self.view_modes[self.view_mode_index]
print(f"Switched to {self.view_mode.upper()} view")
def adjust_contrast(self, delta: float):
"""Adjust CLAHE contrast level"""
self.clahe_contrast = max(1.0, min(8.0, self.clahe_contrast + delta))
print(f"Contrast level: {self.clahe_contrast:.2f}")
# Use enhanced viewer
viewer = EnhancedLiveView()
viewer.run()
Keyboard Controls
q- Quitt- Toggle view mode (YUYV / Temperature / Temperature Celsius)+or=- Increase contrast-or_- Decrease contrastMouse hover - See temperature at cursor position
SPACE- Pause/Resume (for recorded files only)
Command-Line Usage
Run the enhanced live view example from command line:
# Live view (default)
python examples/live_view.py
# Recorded file replay
python examples/live_view.py recordings/thermal_20240101.tseq
# Recorded with custom FPS
python examples/live_view.py file.tseq --fps 30
Record Thermal Frames
from pythermal import ThermalRecorder
rec = ThermalRecorder(output_dir="recordings", color=True)
rec.start() # Starts device and begins recording
rec.record_loop(duration=10) # Record for 10 seconds
rec.stop() # Stop recording
Detect Objects
Detect objects based on temperature ranges:
from pythermal import ThermalCapture, detect_object_centers
capture = ThermalCapture() # Live camera, or pass file path for recorded data
if capture.has_new_frame():
metadata = capture.get_metadata()
temp_array = capture.get_temperature_array()
# Detect objects in temperature range (default: 31-39°C for human body)
objects = detect_object_centers(
temp_array=temp_array,
min_temp=metadata.min_temp,
max_temp=metadata.max_temp,
temp_min=31.0,
temp_max=39.0
)
for obj in objects:
print(f"Object at ({obj.center_x:.1f}, {obj.center_y:.1f}): "
f"{obj.avg_temperature:.1f}°C")
capture.mark_frame_read()
capture.release()
Motion Detection
Detect moving objects using background subtraction:
from pythermal import ThermalCapture, BackgroundSubtractor, detect_moving_objects
capture = ThermalCapture() # Live camera, or pass file path for recorded data
# Initialize background subtractor
bg_subtractor = BackgroundSubtractor(learning_rate=0.01)
if capture.has_new_frame():
metadata = capture.get_metadata()
temp_array = capture.get_temperature_array()
# Detect moving objects
moving_objects, foreground_mask = detect_moving_objects(
temp_array=temp_array,
min_temp=metadata.min_temp,
max_temp=metadata.max_temp,
background_subtractor=bg_subtractor,
temp_threshold=2.0
)
print(f"Detected {len(moving_objects)} moving objects")
capture.mark_frame_read()
capture.release()
ROI Zone Monitoring
Monitor specific regions of interest:
from pythermal import ThermalCapture, ROIManager, detect_object_centers
capture = ThermalCapture() # Live camera, or pass file path for recorded data
# Initialize ROI manager
roi_manager = ROIManager(image_width=96, image_height=96)
# Add center 30x30 ROI
roi_manager.add_center_roi(
size=30,
name="Center",
temp_min=30.0,
temp_max=39.0
)
if capture.has_new_frame():
metadata = capture.get_metadata()
temp_array = capture.get_temperature_array()
# Detect all objects
all_objects = detect_object_centers(
temp_array=temp_array,
min_temp=metadata.min_temp,
max_temp=metadata.max_temp,
temp_min=30.0,
temp_max=39.0
)
# Filter by ROI
roi_objects = roi_manager.filter_objects_by_roi(all_objects)
print(f"Objects in ROI: {len(roi_objects)}")
capture.mark_frame_read()
capture.release()
Multi-Device Support
When multiple thermal cameras are connected, PyThermal automatically assigns consistent device IDs based on USB serial numbers. This ensures that the same physical device always gets the same ID, even after reconnection:
from pythermal import ThermalCapture
# Use device with ID 0 (first device, or smallest available)
capture0 = ThermalCapture(device_index=0)
# Use device with ID 1 (second device)
capture1 = ThermalCapture(device_index=1)
# If no device_index is specified, uses smallest available device ID
capture_auto = ThermalCapture() # Automatically selects smallest available device
# Each device uses separate shared memory:
# Device 0: /dev/shm/yuyv240_shm
# Device 1: /dev/shm/yuyv240_shm_1
# Device 2: /dev/shm/yuyv240_shm_2
# etc.
Device Mapping:
Device IDs are stored persistently in ~/.pythermal/device_mapping.json, mapping USB serial numbers to consistent device IDs. This ensures:
- Same device always gets the same ID (even after reboot)
- Device IDs remain stable across sessions
- Automatic selection of smallest available device when device_index=None