P2DingoCV.HotspotLogic.HotspotDetector
Classes
|
Abstract base class for hotspot detection in thermal or visual frames. |
- class P2DingoCV.HotspotLogic.HotspotDetector.HotspotDetector(outputPath, config=None)[source]
Bases:
objectAbstract base class for hotspot detection in thermal or visual frames.
This class provides core utilities for detecting hotspots using clustering, contrast analysis, and shape metrics. Specific hotspot detection strategies should be implemented in subclasses by overriding
execute().- Parameters:
outputPath (str)
config (str | None)
- outputPath
Directory where results and diagnostics will be saved.
- Type:
str
- utility
Utility object for saving and plotting diagnostics.
- Type:
- labFrame
Current frame converted to CIELAB color space.
- Type:
Frame
- frame
Current raw frame in BGR format.
- Type:
Frame
- frameArea
Total number of pixels in the frame.
- Type:
int
- frameCount
Number of frames processed.
- Type:
int
- k
Number of clusters for k-means segmentation.
- Type:
int
- clusterJoinKernel
Kernel size for morphological joining of clusters.
- Type:
int
- hotSpotThreshold
Score threshold for hotspot classification.
- Type:
float
- sigmoidSteepnessDeltaP
Steepness parameter for ΔP sigmoid scaling.
- Type:
float
- sigmoidSteepnessZ
Steepness parameter for Z-score sigmoid scaling.
- Type:
float
- compactnessCutoff
Normalization cutoff for compactness.
- Type:
float
- dilationSize
Kernel dilation factor for contrast calculation.
- Type:
int
- wDeltaP
Weight for ΔP score in final hotspot scoring.
- Type:
float
- wZscore
Weight for Z-score in final hotspot scoring.
- Type:
float
- wCompactness
Weight for compactness in final hotspot scoring.
- Type:
float
- wAspectRatio
Weight for aspect ratio in final hotspot scoring.
- Type:
float
- wEccentricity
Weight for eccentricity in final hotspot scoring.
- Type:
float
- pixelCounts
Pixel counts per cluster from k-means.
- Type:
np.ndarray
- colours
List of BGR colours for visualization.
- Type:
list[tuple[int, int, int]]
- __init__(outputPath, config=None)[source]
- Parameters:
outputPath (str)
config (str | None)
- Return type:
None
- connectedComponentsFromMask(masks)[source]
Given a list of binary masks, compute connected components for each mask.
Parameters
- maskslist of np.ndarray
Each mask should be a 2D binary image (0/255 or False/True).
Returns
list[list[dict]]
Outer list = per mask Inner list = components in that mask
- Each component dict contains:
‘mask’: binary mask of the component
‘bbox’: (x1, y1, x2, y2)
‘area’: pixel area
‘centroid’: (cx, cy)
- Parameters:
masks (List[numpy.ndarray])
- Return type:
List[List[Dict[str, Any]]]
- determineHotspots(frame, maskArray, saveVisuals)[source]
Determine hotspots across multiple frames.
- Parameters:
frame (Frame) – Input image frame in BGR format.
maskArray (List[Frame]) – List of input binary masks.
saveVisuals (bool) – Whether to save annotated hotspot frames.
- Returns:
List of hotspot detection results for all frames.
Boolean indicating whether any hotspot was detected.
- Return type:
tuple[list, bool]
- dilateHotspots(hotspots)[source]
Dilate the binary masks of hotspots to expand their regions.
This function applies morphological dilation to each hotspot mask within a region of interest (ROI) defined by the hotspot’s bounding box, expanded to avoid clipping. The hotspot dictionaries are updated in-place: - ‘mask’ is modified - ‘bbox’, ‘area’, and ‘centroid’ are recalculated
Parameters
- hotspotslist of dict
- Each dict represents a hotspot and must contain at least:
‘mask’: np.ndarray, binary mask of the hotspot
‘bbox’: tuple (x_min, y_min, x_max, y_max)
Returns
- list of dict
The same list of hotspot dicts with dilated masks and updated properties.
- Parameters:
hotspots (List[Dict[str, Any]])
- Return type:
List[Dict[str, Any]]
- erodeHotspots(hotspots)[source]
Erode the binary masks of hotspots to shrink their regions.
This function applies morphological erosion to each hotspot mask within a region of interest (ROI) defined by the hotspot’s bounding box, expanded to avoid clipping. The hotspot dictionaries are updated in-place: - ‘mask’ is modified - ‘bbox’, ‘area’, and ‘centroid’ are recalculated
Parameters
- hotspotsList[Dict[str, Any]]
- Each dict represents a hotspot and must contain at least:
‘mask’: np.ndarray, binary mask of the hotspot
‘bbox’: tuple (x_min, y_min, x_max, y_max)
Returns
- List[Dict[str, Any]]
The same list of hotspot dicts with eroded masks and updated properties.
- Parameters:
hotspots (List[Dict[str, Any]])
- Return type:
List[Dict[str, Any]]
- filterMask(mask)[source]
Filter out noise regions from a binary mask.
- Parameters:
mask (np.ndarray) – Input binary mask.
- Returns:
Filtered mask containing only valid regions.
- Return type:
np.ndarray
- finalMetricPass(frame, hotspots, otherHotspotMaskFinal)[source]
Compute detailed metrics for each hotspot and return a structured results list.
This method evaluates each hotspot region in the input frame using pixel contrast and shape metrics. The frame is converted to Lab color space, and the L-channel (lightness) is used to compute contrast-based metrics. Shape-based metrics such as compactness, aspect ratio, and eccentricity are also calculated. A combined hotspot score is computed for each hotspot.
Parameters
- frameFrame
Input image/frame in BGR color format.
- hotspotsList[Dict[str, Any]]
- List of hotspot dictionaries to evaluate. Each dictionary should contain at least:
‘mask’: binary mask of the hotspot region
‘area’: area of the hotspot
‘centroid’: (x, y) coordinates of the hotspot centroid
- otherHotspotMaskFinalFrame
Binary mask representing other hotspots (not used in current placeholder logic).
Returns
- List[Tuple]
- List of tuples containing metrics for each hotspot in the following format:
- (
index, # Index of the hotspot in the input list hotspotScore, # Combined hotspot score None, # Placeholder (currently unused) centroid, # Centroid coordinates (x, y) deltaPScore, # Pixel contrast score deltaPRobust, # Robust pixel contrast zScore, # Raw z-score for contrast zScoreNorm, # Normalized z-score compactness, # Shape compactness aspectRatioNorm,# Normalized aspect ratio eccentricity, # Shape eccentricity area # Hotspot area
)
Notes
Uses helper methods pixelContrast, shapeAndCompactness, and hotSpotScore.
The otherHotspotMaskFinal parameter is currently not used in the pixel contrast calculation.
Designed as the final evaluation pass to generate a comprehensive metric set for downstream processing or reporting.
- Parameters:
frame (numpy.ndarray)
hotspots (List[Dict[str, Any]])
otherHotspotMaskFinal (numpy.ndarray)
- Return type:
List[Tuple]
- higherOrderOverlap(componentsFirstLayer, componentsSecondLayer)[source]
Compute overlaps between two layers of component masks and merge them.
For each component in componentsFirstLayer, this method checks for overlapping bounding boxes with components in componentsSecondLayer. If an overlap exists and their masks intersect, a new merged component is created with:
A mask that is the union of the overlapping masks.
An updated bounding box covering both components.
Recalculated area based on the combined mask.
Centroid computed as the center of the new bounding box.
Parameters
- componentsFirstLayerList[Dict[str, Any]]
List of component dictionaries in the first layer. Each dictionary must contain at least:
‘mask’: numpy array representing the component mask
‘bbox’: tuple (x_min, y_min, x_max, y_max) defining the bounding box
- componentsSecondLayerList[Dict[str, Any]]
List of component dictionaries in the second layer. Each dictionary must contain at least ‘mask’ and ‘bbox’, same as above.
Returns
- List[Dict[str, Any]]
- A list of merged component dictionaries with keys:
‘mask’: combined mask of overlapping components
‘bbox’: updated bounding box
‘area’: area of the combined mask
‘centroid’: center coordinates of the new bounding box
- Parameters:
componentsFirstLayer (List[Dict[str, Any]])
componentsSecondLayer (List[Dict[str, Any]])
- Return type:
List[Dict[str, Any]]
- hotSpotScore(deltaPScore, zScoreNorm, compactness, aspectRatio, eccentricity)[source]
Compute a weighted hotspot score.
- Parameters:
deltaPScore (float) – Probability score from robust ΔP.
zScoreNorm (float) – Normalized Z-score.
compactness (float) – Compactness of the hotspot region.
aspectRatio (float) – Aspect ratio of the hotspot region.
eccentricity (float) – Eccentricity of the hotspot region.
- Returns:
Final weighted hotspot score.
- Return type:
float
- hotspotMetricPass(frame, canididates, otherHotspotsMask)[source]
Evaluate candidate regions in a frame and select those that qualify as hotspots based on intensity contrast, shape, and compactness metrics.
This method converts the input frame to the Lab color space and analyzes the L-channel (lightness) to assess pixel contrast for each candidate region. Additional metrics, such as shape compactness, aspect ratio, and eccentricity, are also computed. A combined hotspot score is calculated, and candidates with a score above the threshold are returned as detected hotspots.
Parameters
- frameFrame
The input image/frame in BGR color format.
canididates : List[Dict[str, Any]]
A list of candidate regions to evaluate. Each candidate dictionary should contain at least: - ‘mask’: binary mask of the candidate region - ‘area’: area of the candidate region
- otherHotspotsMaskFrame
Binary mask representing other already-detected hotspots. Used to exclude overlapping pixels when computing contrast.
Returns
- List[Dict[str, Any]]
List of candidate dictionaries that passed the hotspot score threshold.
- List[Dict[str, Any]]
List of candidate dictionaries that failed the hotspot score threshold.
Notes
- The method relies on pixelContrast, shapeAndCompactness, and hotSpotScore
helper methods to compute the necessary metrics for each candidate.
- hotSpotThreshold is a class attribute that defines the minimum score for a
region to be considered a hotspot.
- Parameters:
frame (numpy.ndarray)
canididates (List[Dict[str, Any]])
otherHotspotsMask (numpy.ndarray)
- Return type:
Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]
- kMeansThermalGrouping(frame, saveDiagonstics)[source]
Cluster pixels into thermal groups using k-means.
- Parameters:
frame (Frame) – Input frame in BGR format.
saveDiagonstics (bool) – Whether to save segmented outputs.
- Returns:
List of binary masks for each k-means cluster.
- Return type:
List[Frame]
- layeredCandidates(componentsArray, depthLimit=3)[source]
Generate a flattened list of candidate components by progressively combining layers of components.
This method starts with the first layer of components and iteratively merges it with subsequent layers using the higherOrderOverlap method. The result is a single list of candidate components that accounts for overlaps or relationships between layers.
Parameters
- componentsArrayList[List[Dict[str, Any]]]
A list of layers, where each layer is a list of component dictionaries. Each component dictionary contains attributes describing a detected component (e.g., bounding box, confidence score, etc.).
Returns
- List[Dict[str, Any]]
A flattened list of candidate components after combining all layers. Components from higher layers that overlap or relate to existing candidates are included according to the logic in higherOrderOverlap.
Notes
- The higherOrderOverlap method is responsible for determining which components
from the next layer should be merged with the current candidates.
The first layer of components is always included in the returned list.
- Parameters:
componentsArray (List[List[Dict[str, Any]]])
depthLimit (int)
- Return type:
List[Dict[str, Any]]
- loadConfig(configPath)[source]
Load hotspot detector parameters from a JSON configuration file.
This will overwrite the default tunable parameters set in __init__.
- Parameters:
config_path (str) – Path to the JSON configuration file.
configPath (str)
- Raises:
FileNotFoundError – If the config file does not exist.
json.JSONDecodeError – If the config file is not valid JSON.
- Return type:
None
- mergeOverlappingHotspots(hotspots)[source]
Merge overlapping hotspot regions into unified hotspots.
This method iteratively examines each pair of hotspot regions and merges them if their bounding boxes overlap and their masks have any intersecting pixels. The merged hotspot’s mask is the union of the overlapping masks, its bounding box is expanded to cover both regions, and the area and centroid are recalculated based on the combined mask. The process continues until no further merges are possible.
Parameters
- hotspotsList[Dict[str, Any]]
- A list of hotspot dictionaries, each containing at least:
‘mask’: binary mask of the hotspot (np.uint8)
‘bbox’: bounding box as (x_min, y_min, x_max, y_max)
Optional fields will be recalculated (area, centroid) during merging.
Returns
- List[Dict[str, Any]]
- List of merged hotspots, each with updated:
‘mask’: merged binary mask
‘bbox’: updated bounding box covering all merged regions
‘area’: total area of the merged mask
‘centroid’: true centroid of the merged mask
Notes
Masks are ensured to be binary (0 or 255) before merging.
- Centroid is computed from the mask using image moments; if the mask is empty,
the centroid defaults to the center of the bounding box.
The method uses iterative merging until no overlapping hotspots remain.
- Parameters:
hotspots (List[Dict[str, Any]])
- Return type:
List[Dict[str, Any]]
- perFrameProcessing(frame, saveFrames, diagonstics, frameCount)[source]
Process a single frame through the hotspot detection pipeline.
- Parameters:
frame (Frame) – Input image frame in BGR format.
saveFrames (bool) – Whether to save visual outputs.
diagonstics (bool) – Whether to save intermediate diagnostic results.
frameCount (int)
- Returns:
List of hotspot detection results for this frame.
Boolean indicating whether a hotspot was detected.
- Return type:
tuple[list, bool]
- perFrameSetup(frame)[source]
Initialize state for a new frame.
Resets internal counters, computes frame area, and sets up per-frame parameters.
- Parameters:
frame (Frame) – Input frame in BGR format.
- Returns:
The original frame after setup.
- Return type:
Frame
- pixelContrast(LChannel, componentMask, otherHotspotsMask, area, optimised=True)[source]
Compute contrast metrics for a hotspot region.
- Parameters:
LChannel (Frame) – Luminance channel of LAB frame.
componentMask (Frame) – Mask of the region of interest.
otherHotspotsMask (Frame) – Mask of other hotspots to exclude.
area (float) – Pixel area of the region.
optimised (bool) – Whether to use optimized percentile calculation.
- Returns:
Robust ΔP contrast.
Global Z-score.
ΔP probability score.
Normalized Z-score.
Mask of Inspected Areas
- Return type:
tuple[float, float, float, float, Frame]
- pixelToTemp(pixelVal)[source]
Convert a pixel value to temperature using calibration.
- Parameters:
pixelVal (float) – Pixel luminance value.
- Returns:
Estimated temperature.
- Return type:
float
- Raises:
TempDetectionFailed – If calibration parameters are missing.
- processingDiagonstics()[source]
Plot diagnostic data such as pixel count distributions.
Saves plots to the configured output path.
- Return type:
None
- resetFrameData()[source]
Reset frame-dependent state variables.
Resets temperature calibration, frame buffers, and cluster statistics.
- Return type:
None
- robustConstrastStretch(region, lower_pct=1, upper_pct=99)[source]
Perform a robust contrast stretch on an image region using percentiles.
This method rescales the pixel intensities of region so that the intensity at lower_pct maps to 0 and the intensity at upper_pct maps to 255, effectively stretching the contrast while ignoring extreme outliers.
Parameters
- regionFrame
Input image region as a numpy array. Can be grayscale or single-channel.
- lower_pctfloat, optional (default=1)
Lower percentile used for contrast stretching. Pixels below this percentile are clipped to 0.
- upper_pctfloat, optional (default=99)
Upper percentile used for contrast stretching. Pixels above this percentile are clipped to 255.
Returns
- Frame
Contrast-stretched image region as a numpy array of type np.uint8. Returns a copy of the input if the region is empty or if p_high - p_low == 0.
- Parameters:
region (numpy.ndarray)
- Return type:
numpy.ndarray
- shapeAndCompactness(componentMask, area)[source]
Calculate shape metrics for a region.
- Parameters:
componentMask (Frame) – Binary mask of a connected component.
area (float) – Pixel area of the component.
- Returns:
Normalized compactness.
Aspect ratio.
Eccentricity (or aspect ratio if ellipse fitting fails).
- Return type:
tuple[float, float, float]