Spaces:
Sleeping
Sleeping
import cv2 | |
import numpy as np | |
import matplotlib.pyplot as plt | |
import seaborn as sns | |
from image_processor import ImageProcessor | |
class HeatmapGenerator: | |
def __init__(self): | |
""" | |
Initialize the heatmap generator for visualizing threat areas | |
""" | |
self.image_processor = ImageProcessor() | |
# Define colormap options | |
self.colormap_options = { | |
'hot': cv2.COLORMAP_HOT, # Red-yellow-white, good for high intensity | |
'jet': cv2.COLORMAP_JET, # Blue-cyan-yellow-red, good for range | |
'inferno': cv2.COLORMAP_INFERNO, # Purple-red-yellow, good for threat | |
'plasma': cv2.COLORMAP_PLASMA # Purple-red-yellow, alternative | |
} | |
# Default colormap | |
self.default_colormap = 'inferno' | |
def generate_heatmap_from_diff(self, diff_image, threshold=0, blur_size=15): | |
""" | |
Generate a heatmap directly from a difference image | |
Args: | |
diff_image: Difference image (0-255 range) | |
threshold: Minimum difference value to consider (0-255) | |
blur_size: Size of Gaussian blur kernel for smoothing | |
Returns: | |
Heatmap image | |
""" | |
# Apply threshold to filter out low differences | |
_, thresholded = cv2.threshold(diff_image, threshold, 255, cv2.THRESH_TOZERO) | |
# Apply Gaussian blur to smooth the heatmap | |
if blur_size > 0: | |
blurred = cv2.GaussianBlur(thresholded, (blur_size, blur_size), 0) | |
else: | |
blurred = thresholded | |
# Apply colormap | |
heatmap = cv2.applyColorMap(blurred, self.colormap_options[self.default_colormap]) | |
# Convert to RGB for consistent display | |
heatmap_rgb = cv2.cvtColor(heatmap, cv2.COLOR_BGR2RGB) | |
return heatmap_rgb | |
def generate_heatmap_from_regions(self, image_shape, labeled_regions, sigma=40): | |
""" | |
Generate a heatmap from labeled regions based on threat levels | |
Args: | |
image_shape: Shape of the original image (height, width) | |
labeled_regions: List of regions with threat levels from ThreatLabeler | |
sigma: Standard deviation for Gaussian kernel | |
Returns: | |
Heatmap image | |
""" | |
# Create an empty heatmap | |
height, width = image_shape[:2] | |
heatmap = np.zeros((height, width), dtype=np.float32) | |
# Define threat level weights with increased intensity | |
threat_weights = { | |
'low': 0.4, | |
'medium': 0.7, | |
'high': 1.0 | |
} | |
# Add each region to the heatmap with appropriate weight | |
for region in labeled_regions: | |
bbox = region['bbox'] | |
threat_level = region['threat_level'] | |
diff_percentage = region['difference_percentage'] | |
# Calculate center of bounding box | |
x, y, w, h = bbox | |
center_x, center_y = x + w // 2, y + h // 2 | |
# Calculate intensity based on threat level and difference percentage with increased brightness | |
intensity = threat_weights[threat_level] * (diff_percentage / 100) * 1.2 | |
# Create a Gaussian kernel centered at the region with increased sigma for more circular spread | |
y_coords, x_coords = np.ogrid[:height, :width] | |
dist_from_center = ((y_coords - center_y) ** 2 + (x_coords - center_x) ** 2) / (2 * sigma ** 2) | |
kernel = np.exp(-dist_from_center) * intensity | |
# Add to heatmap | |
heatmap += kernel | |
# Normalize heatmap to 0-255 range | |
if np.max(heatmap) > 0: # Avoid division by zero | |
heatmap = (heatmap / np.max(heatmap) * 255).astype(np.uint8) | |
else: | |
heatmap = np.zeros((height, width), dtype=np.uint8) | |
# Apply colormap | |
colored_heatmap = cv2.applyColorMap(heatmap, self.colormap_options[self.default_colormap]) | |
colored_heatmap = cv2.cvtColor(colored_heatmap, cv2.COLOR_BGR2RGB) | |
return colored_heatmap | |
def overlay_heatmap(self, original_image, heatmap, alpha=0.6): | |
""" | |
Overlay heatmap on original image | |
Args: | |
original_image: Original image | |
heatmap: Heatmap image | |
alpha: Transparency factor (0-1) | |
Returns: | |
Overlaid image | |
""" | |
# Ensure images are the same size | |
if original_image.shape[:2] != heatmap.shape[:2]: | |
heatmap = cv2.resize(heatmap, (original_image.shape[1], original_image.shape[0])) | |
# Overlay heatmap on original image | |
return self.image_processor.overlay_images(original_image, heatmap, alpha) | |
def generate_threat_heatmap(self, image, labeled_regions, overlay=True, alpha=0.6): | |
""" | |
Generate a complete threat heatmap visualization | |
Args: | |
image: Original image | |
labeled_regions: List of regions with threat levels | |
overlay: Whether to overlay on original image | |
alpha: Transparency for overlay | |
Returns: | |
Heatmap image or overlaid image | |
""" | |
# Generate heatmap from labeled regions | |
heatmap = self.generate_heatmap_from_regions(image.shape, labeled_regions) | |
# Overlay on original image if requested | |
if overlay: | |
return self.overlay_heatmap(image, heatmap, alpha) | |
else: | |
return heatmap | |
def save_heatmap_visualization(self, image, heatmap, output_path, dpi=300): | |
""" | |
Save a side-by-side visualization of original image and heatmap | |
Args: | |
image: Original image | |
heatmap: Heatmap image | |
output_path: Path to save visualization | |
dpi: Resolution for saved image | |
""" | |
# Create figure with two subplots | |
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6)) | |
# Display original image | |
ax1.imshow(image) | |
ax1.set_title('Original Image') | |
ax1.axis('off') | |
# Display heatmap | |
ax2.imshow(heatmap) | |
ax2.set_title('Threat Heatmap') | |
ax2.axis('off') | |
# Save figure | |
plt.tight_layout() | |
plt.savefig(output_path, dpi=dpi, bbox_inches='tight') | |
plt.close() | |
def generate_multi_level_heatmap(self, image, labeled_regions): | |
""" | |
Generate separate heatmaps for each threat level | |
Args: | |
image: Original image | |
labeled_regions: List of regions with threat levels | |
Returns: | |
Dictionary with heatmaps for each threat level and combined | |
""" | |
# Create separate lists for each threat level | |
low_regions = [r for r in labeled_regions if r['threat_level'] == 'low'] | |
medium_regions = [r for r in labeled_regions if r['threat_level'] == 'medium'] | |
high_regions = [r for r in labeled_regions if r['threat_level'] == 'high'] | |
# Generate heatmaps for each level | |
low_heatmap = self.generate_heatmap_from_regions(image.shape, low_regions) | |
medium_heatmap = self.generate_heatmap_from_regions(image.shape, medium_regions) | |
high_heatmap = self.generate_heatmap_from_regions(image.shape, high_regions) | |
# Generate combined heatmap | |
combined_heatmap = self.generate_heatmap_from_regions(image.shape, labeled_regions) | |
# Overlay all on original image | |
combined_overlay = self.overlay_heatmap(image, combined_heatmap) | |
return { | |
'low': low_heatmap, | |
'medium': medium_heatmap, | |
'high': high_heatmap, | |
'combined': combined_heatmap, | |
'overlay': combined_overlay | |
} |