Detection Modules
Utilities
Shared utilities for thermal object detection.
Provides common data structures and utility functions used across different detection modules.
- class pythermal.detections.utils.DetectedObject(center_x: float, center_y: float, width: int, height: int, area: int, avg_temperature: float, max_temperature: float, min_temperature: float)[source]
Bases:
objectRepresents a detected object with its center and properties
- pythermal.detections.utils.convert_to_celsius(temp_array: ndarray, min_temp: float, max_temp: float) ndarray[source]
Convert temperature array to Celsius.
- Parameters:
temp_array – Temperature array (uint16 or float32)
min_temp – Minimum temperature in Celsius from metadata
max_temp – Maximum temperature in Celsius from metadata
- Returns:
Temperature array in Celsius (float32)
- pythermal.detections.utils.cluster_objects(objects: List[DetectedObject], max_distance: float = 30.0) List[List[DetectedObject]][source]
Cluster detected objects that are close to each other.
Uses simple distance-based clustering.
- Parameters:
objects – List of DetectedObject instances
max_distance – Maximum distance between objects to be in the same cluster (default: 30.0)
- Returns:
List of clusters, where each cluster is a list of DetectedObject instances
- pythermal.detections.utils.calculate_aspect_ratio(obj: DetectedObject) float[source]
Calculate aspect ratio of detected object.
- Parameters:
obj – DetectedObject instance
- Returns:
Aspect ratio (width/height). Values > 1.0 indicate wider objects.
- pythermal.detections.utils.calculate_compactness(obj: DetectedObject) float[source]
Calculate compactness (circularity approximation) of detected object.
Uses bounding box approximation: 4π*area/(width+height)² Higher values (closer to 1.0) indicate more circular/compact objects.
- Parameters:
obj – DetectedObject instance
- Returns:
Compactness value (0.0 to 1.0)
- pythermal.detections.utils.calculate_circularity(contour: ndarray, area: float) float[source]
Calculate true circularity from contour.
Circularity = 4π*area/perimeter² Higher values (closer to 1.0) indicate more circular objects.
- Parameters:
contour – Contour points (numpy array)
area – Contour area
- Returns:
Circularity value (0.0 to 1.0)
- pythermal.detections.utils.calculate_convexity_ratio(contour: ndarray, area: float) float[source]
Calculate convexity ratio from contour.
Convexity = area / convex_hull_area Higher values (closer to 1.0) indicate more convex objects.
- Parameters:
contour – Contour points (numpy array)
area – Contour area
- Returns:
Convexity ratio (0.0 to 1.0)
- pythermal.detections.utils.filter_by_aspect_ratio(objects: List[DetectedObject], min_ratio: float | None = None, max_ratio: float | None = None) List[DetectedObject][source]
Filter objects by aspect ratio (width/height).
- Parameters:
objects – List of DetectedObject instances
min_ratio – Minimum aspect ratio (default: None, no minimum)
max_ratio – Maximum aspect ratio (default: None, no maximum)
- Returns:
Filtered list of objects
- pythermal.detections.utils.filter_by_compactness(objects: List[DetectedObject], min_compactness: float | None = None, max_compactness: float | None = None) List[DetectedObject][source]
Filter objects by compactness (circularity approximation).
- Parameters:
objects – List of DetectedObject instances
min_compactness – Minimum compactness (default: None, no minimum)
max_compactness – Maximum compactness (default: None, no maximum)
- Returns:
Filtered list of objects
- pythermal.detections.utils.filter_by_area(objects: List[DetectedObject], min_area: int | None = None, max_area: int | None = None) List[DetectedObject][source]
Filter objects by area.
- Parameters:
objects – List of DetectedObject instances
min_area – Minimum area in pixels (default: None, no minimum)
max_area – Maximum area in pixels (default: None, no maximum)
- Returns:
Filtered list of objects
- pythermal.detections.utils.filter_by_shape(objects: List[DetectedObject], min_aspect_ratio: float | None = None, max_aspect_ratio: float | None = None, min_compactness: float | None = None, max_compactness: float | None = None, min_area: int | None = None, max_area: int | None = None) List[DetectedObject][source]
Filter objects by multiple shape criteria.
Convenience function that applies all shape filters at once.
- Parameters:
objects – List of DetectedObject instances
min_aspect_ratio – Minimum aspect ratio (width/height)
max_aspect_ratio – Maximum aspect ratio (width/height)
min_compactness – Minimum compactness (0.0-1.0)
max_compactness – Maximum compactness (0.0-1.0)
min_area – Minimum area in pixels
max_area – Maximum area in pixels
- Returns:
Filtered list of objects
Temperature Detection
Temperature-based object detection.
Provides functions to detect objects based on temperature ranges.
- pythermal.detections.temperature_detection.detect_object_centers(temp_array: ndarray, min_temp: float, max_temp: float, temp_min: float = 31.0, temp_max: float = 39.0, min_area: int = 50) List[DetectedObject][source]
Detect object centers from temperature map based on temperature range.
- Parameters:
temp_array – Temperature array (96x96, uint16 or float32)
min_temp – Minimum temperature in Celsius from metadata
max_temp – Maximum temperature in Celsius from metadata
temp_min – Minimum temperature threshold in Celsius (default: 31.0 for human body)
temp_max – Maximum temperature threshold in Celsius (default: 39.0 for human body)
min_area – Minimum area in pixels for detected objects (default: 50)
- Returns:
List of DetectedObject instances with center coordinates and properties
- pythermal.detections.temperature_detection.detect_humans_adaptive(temp_array: ndarray, min_temp: float, max_temp: float, environment_temp: float | None = None, alpha_min: float = 0.4, alpha_max: float = 0.7, core_temp: float = 37.0, min_area: int = 50, temp_margin: float = 2.0, min_temp_above_env: float = 2.0, max_temp_limit: float = 42.0, max_aspect_ratio: float = 4.0, min_aspect_ratio: float = 0.4) List[DetectedObject][source]
Advanced human detection using adaptive temperature thresholds based on environment temperature.
This method estimates the expected body temperature range from the environment temperature using the formula: Ts = Te + α × (Tc − Te)
Where: - Ts = Skin temperature (estimated body temperature) - Te = Environment temperature - Tc = Core body temperature (default: 37°C) - α = Blood flow regulation coefficient (0.5-0.7 for face/torso)
The detection focuses on warmer body parts (face/torso) and includes additional filters: - Minimum temperature above environment (to exclude cold objects) - Maximum temperature limit (to exclude hot objects like heaters) - Aspect ratio filtering (to match human body proportions) - Temperature consistency checks
- Parameters:
temp_array – Temperature array (96x96, uint16 or float32)
min_temp – Minimum temperature in Celsius from metadata
max_temp – Maximum temperature in Celsius from metadata
environment_temp – Environment/room temperature in Celsius. If None, will be estimated from the frame using the 5th percentile method.
alpha_min – Minimum alpha value for detection (default: 0.4, includes some cooler body parts)
alpha_max – Maximum alpha value for detection (default: 0.7, face/torso)
core_temp – Core body temperature in Celsius (default: 37.0)
min_area – Minimum area in pixels for detected objects (default: 50)
temp_margin – Temperature margin in Celsius to add around estimated range (default: 2.0)
min_temp_above_env – Minimum temperature above environment to consider (default: 2.0°C) This helps exclude objects that are only slightly warmer than room
max_temp_limit – Maximum temperature limit to avoid detecting very hot objects (default: 42.0°C)
max_aspect_ratio – Maximum aspect ratio (width/height or height/width) for human detection (default: 4.0)
min_aspect_ratio – Minimum aspect ratio for human detection (default: 0.4)
- Returns:
List of DetectedObject instances representing detected humans
Examples
>>> # Detect humans with estimated environment temperature >>> objects = detect_humans_adaptive(temp_array, min_temp, max_temp)
>>> # Detect humans with known room temperature >>> objects = detect_humans_adaptive(temp_array, min_temp, max_temp, environment_temp=22.0)
Motion Detection
Motion detection using background subtraction.
Provides background subtraction and motion detection for thermal images.
- class pythermal.detections.motion_detection.BackgroundSubtractor(learning_rate: float = 0.01, history_size: int = 30, min_frames_for_background: int = 10)[source]
Bases:
objectBackground subtraction for thermal images using running average.
Maintains a background model and detects moving objects by comparing current frame to the background.
- __init__(learning_rate: float = 0.01, history_size: int = 30, min_frames_for_background: int = 10)[source]
Initialize background subtractor.
- Parameters:
learning_rate – Rate at which background model updates (0.0-1.0, default: 0.01) Lower values = slower adaptation, more stable background
history_size – Number of frames to keep in history for median-based background (default: 30)
min_frames_for_background – Minimum frames needed before background is considered stable (default: 10)
- update(temp_celsius: ndarray) ndarray[source]
Update background model with new frame.
- Parameters:
temp_celsius – Temperature array in Celsius (float32)
- Returns:
Foreground mask (binary, uint8) - pixels that differ from background
- pythermal.detections.motion_detection.detect_moving_objects(temp_array: ndarray, min_temp: float, max_temp: float, background_subtractor: BackgroundSubtractor, temp_threshold: float = 2.0, min_area: int = 50, combine_with_temp_range: bool = True, temp_min: float | None = None, temp_max: float | None = None) Tuple[List[DetectedObject], ndarray][source]
Detect moving objects using background subtraction.
- Parameters:
temp_array – Temperature array (96x96, uint16 or float32)
min_temp – Minimum temperature in Celsius from metadata
max_temp – Maximum temperature in Celsius from metadata
background_subtractor – BackgroundSubtractor instance
temp_threshold – Temperature difference threshold in Celsius for motion detection (default: 2.0)
min_area – Minimum area in pixels for detected objects (default: 50)
combine_with_temp_range – If True, also filter by temperature range (default: True)
temp_min – Minimum temperature for filtering (only used if combine_with_temp_range=True)
temp_max – Maximum temperature for filtering (only used if combine_with_temp_range=True)
- Returns:
Tuple of (list of DetectedObject instances, foreground mask)
ROI Management
Region of Interest (ROI) support for thermal detection.
Provides ROI management and zone monitoring capabilities.
- class pythermal.detections.roi.ROI(x: int, y: int, width: int, height: int, name: str = 'ROI', temp_min: float | None = None, temp_max: float | None = None)[source]
Bases:
objectRegion of Interest definition.
Represents a rectangular region with optional temperature thresholds.
- class pythermal.detections.roi.ROIManager(image_width: int = 96, image_height: int = 96)[source]
Bases:
objectManages multiple ROIs for zone monitoring.
Supports multiple ROIs with different temperature thresholds.
- __init__(image_width: int = 96, image_height: int = 96)[source]
Initialize ROI manager.
- Parameters:
image_width – Width of the thermal image (default: 96)
image_height – Height of the thermal image (default: 96)
- add_roi(x: int, y: int, width: int, height: int, name: str = 'ROI', temp_min: float | None = None, temp_max: float | None = None) ROI[source]
Add a new ROI.
- Parameters:
x – X coordinate of top-left corner
y – Y coordinate of top-left corner
width – Width of ROI
height – Height of ROI
name – Name/label for this ROI
temp_min – Optional minimum temperature threshold for this ROI
temp_max – Optional maximum temperature threshold for this ROI
- Returns:
The created ROI instance
- add_center_roi(size: int = 30, name: str = 'Center', temp_min: float | None = None, temp_max: float | None = None) ROI[source]
Add a centered ROI.
- Parameters:
size – Size of the square ROI (default: 30)
name – Name/label for this ROI
temp_min – Optional minimum temperature threshold for this ROI
temp_max – Optional maximum temperature threshold for this ROI
- Returns:
The created ROI instance
- remove_roi(name: str) bool[source]
Remove ROI by name.
- Parameters:
name – Name of ROI to remove
- Returns:
True if ROI was found and removed, False otherwise
- get_combined_mask() ndarray[source]
Get combined mask for all ROIs.
- Returns:
Binary mask (uint8) where any ROI region is 255, rest is 0
- filter_objects_by_roi(objects: List[DetectedObject], roi_name: str | None = None) List[DetectedObject][source]
Filter detected objects to only include those within ROI(s).
- Parameters:
objects – List of detected objects
roi_name – If specified, only filter by this ROI. Otherwise, filter by all ROIs.
- Returns:
Filtered list of objects within ROI(s)
- filter_objects_by_temperature(objects: List[DetectedObject], temp_celsius: ndarray, roi_name: str | None = None) List[DetectedObject][source]
Filter detected objects by ROI temperature thresholds.
- Parameters:
objects – List of detected objects
temp_celsius – Temperature array in Celsius
roi_name – If specified, only check this ROI. Otherwise, check all ROIs.
- Returns:
Filtered list of objects that meet ROI temperature criteria
- get_roi_statistics(temp_celsius: ndarray, roi_name: str | None = None) Dict[str, Dict[str, float]][source]
Get temperature statistics for each ROI.
- Parameters:
temp_celsius – Temperature array in Celsius
roi_name – If specified, only get stats for this ROI. Otherwise, get stats for all ROIs.
- Returns:
Dictionary mapping ROI names to their statistics (min, max, avg)
YOLO Detection
YOLO Object Detection
YOLO v11 Object Detection for Thermal Images
Provides object detection using YOLO v11 models. Supports both default official models and custom thermal-specific models.
- class pythermal.detections.yolo.object_detection.YOLOObjectDetector(model_path: str | None = None, model_size: str = 'nano', conf_threshold: float = 0.25, iou_threshold: float = 0.45, device: str | None = None)[source]
Bases:
objectYOLO v11 Object Detector for thermal images.
Supports both default official YOLO v11 models and custom thermal-specific models. Models are automatically downloaded on first use if not present.
- DEFAULT_MODEL = 'yolo11n.pt'
- MODEL_OPTIONS = {'large': 'yolo11l.pt', 'medium': 'yolo11m.pt', 'nano': 'yolo11n.pt', 'small': 'yolo11s.pt', 'xlarge': 'yolo11x.pt'}
- __init__(model_path: str | None = None, model_size: str = 'nano', conf_threshold: float = 0.25, iou_threshold: float = 0.45, device: str | None = None)[source]
Initialize YOLO object detector.
- Parameters:
model_path – Path to custom model file. If None, uses default official model. Can be absolute path or relative to models directory.
model_size – Model size for default model (“nano”, “small”, “medium”, “large”, “xlarge”). Only used if model_path is None.
conf_threshold – Confidence threshold for detections (0.0-1.0)
iou_threshold – IoU threshold for NMS (0.0-1.0)
device – Device to run inference on (“cpu”, “cuda”, “mps”, etc.). If None, auto-detects.
- Raises:
ImportError – If ultralytics package is not installed
FileNotFoundError – If custom model file is not found
- detect(image: ndarray, classes: List[int] | None = None, verbose: bool = False) List[Dict[str, Any]][source]
Detect objects in thermal image.
- Parameters:
image – Input image (BGR or RGB, numpy array)
classes – List of class IDs to detect (None = all classes)
verbose – Whether to print detection details
- Returns:
“bbox”: [x1, y1, x2, y2] bounding box coordinates
”confidence”: Detection confidence (0.0-1.0)
”class_id”: Class ID
”class_name”: Class name
”center”: (x, y) center coordinates
”width”: Bounding box width
”height”: Bounding box height
- Return type:
List of detection dictionaries, each containing
- detect_batch(images: List[ndarray], classes: List[int] | None = None, verbose: bool = False) List[List[Dict[str, Any]]][source]
Detect objects in multiple images (batch processing).
- Parameters:
images – List of input images
classes – List of class IDs to detect (None = all classes)
verbose – Whether to print detection details
- Returns:
List of detection lists (one per image)
- get_class_names() Dict[int, str][source]
Get mapping of class IDs to class names.
- Returns:
Dictionary mapping class_id -> class_name
- visualize(image: ndarray, detections: List[Dict[str, Any]], show_labels: bool = True, show_conf: bool = True) ndarray[source]
Visualize detections on image.
- Parameters:
image – Input image (BGR format)
detections – List of detection dictionaries from detect()
show_labels – Whether to show class labels
show_conf – Whether to show confidence scores
- Returns:
Image with detections drawn (BGR format)
YOLO Pose Detection
YOLO v11 Pose Detection for Thermal Images
Provides pose/keypoint detection using YOLO v11 pose models. Supports both default official models and custom thermal-specific models.
- class pythermal.detections.yolo.pose_detection.YOLOPoseDetector(model_path: str | None = None, model_size: str = 'nano', conf_threshold: float = 0.25, iou_threshold: float = 0.45, device: str | None = None)[source]
Bases:
objectYOLO v11 Pose Detector for thermal images.
Supports both default official YOLO v11 pose models and custom thermal-specific models. Models are automatically downloaded on first use if not present.
- DEFAULT_MODEL = 'yolo11n-pose.pt'
- MODEL_OPTIONS = {'large': 'yolo11l-pose.pt', 'medium': 'yolo11m-pose.pt', 'nano': 'yolo11n-pose.pt', 'small': 'yolo11s-pose.pt', 'xlarge': 'yolo11x-pose.pt'}
- KEYPOINT_NAMES = ['nose', 'left_eye', 'right_eye', 'left_ear', 'right_ear', 'left_shoulder', 'right_shoulder', 'left_elbow', 'right_elbow', 'left_wrist', 'right_wrist', 'left_hip', 'right_hip', 'left_knee', 'right_knee', 'left_ankle', 'right_ankle']
- SKELETON_CONNECTIONS = [(0, 1), (0, 2), (1, 3), (2, 4), (5, 6), (5, 11), (6, 12), (11, 12), (5, 7), (7, 9), (6, 8), (8, 10), (11, 13), (13, 15), (12, 14), (14, 16)]
- __init__(model_path: str | None = None, model_size: str = 'nano', conf_threshold: float = 0.25, iou_threshold: float = 0.45, device: str | None = None)[source]
Initialize YOLO pose detector.
- Parameters:
model_path – Path to custom model file. If None, uses default official model. Can be absolute path or relative to models directory.
model_size – Model size for default model (“nano”, “small”, “medium”, “large”, “xlarge”). Only used if model_path is None.
conf_threshold – Confidence threshold for detections (0.0-1.0)
iou_threshold – IoU threshold for NMS (0.0-1.0)
device – Device to run inference on (“cpu”, “cuda”, “mps”, etc.). If None, auto-detects.
- Raises:
ImportError – If ultralytics package is not installed
FileNotFoundError – If custom model file is not found
- detect(image: ndarray, verbose: bool = False) List[Dict[str, Any]][source]
Detect poses/keypoints in thermal image.
- Parameters:
image – Input image (BGR or RGB, numpy array)
verbose – Whether to print detection details
- Returns:
“bbox”: [x1, y1, x2, y2] bounding box coordinates
”confidence”: Detection confidence (0.0-1.0)
”keypoints”: List of (x, y, confidence) tuples for each keypoint (17 keypoints)
”keypoints_dict”: Dictionary mapping keypoint names to (x, y, confidence)
”center”: (x, y) center coordinates of person
”width”: Bounding box width
”height”: Bounding box height
- Return type:
List of pose detection dictionaries, each containing
- detect_batch(images: List[ndarray], verbose: bool = False) List[List[Dict[str, Any]]][source]
Detect poses in multiple images (batch processing).
- Parameters:
images – List of input images
verbose – Whether to print detection details
- Returns:
List of pose detection lists (one per image)
- visualize(image: ndarray, detections: List[Dict[str, Any]], show_bbox: bool = True, show_keypoints: bool = True, show_skeleton: bool = True, show_labels: bool = False, keypoint_radius: int = 3, skeleton_thickness: int = 2) ndarray[source]
Visualize pose detections on image.
- Parameters:
image – Input image (BGR format)
detections – List of pose detection dictionaries from detect()
show_bbox – Whether to show bounding boxes
show_keypoints – Whether to show keypoints
show_skeleton – Whether to show skeleton connections
show_labels – Whether to show keypoint labels
keypoint_radius – Radius of keypoint circles
skeleton_thickness – Thickness of skeleton lines
- Returns:
Image with pose detections drawn (BGR format)