Spaces:
Sleeping
Sleeping
| """Gaussian density heatmap from car detections.""" | |
| import cv2 | |
| import numpy as np | |
| def generate_heatmap(image: np.ndarray, detections: list[dict]) -> np.ndarray: | |
| """Create a density heatmap blended with the original image. | |
| Places impulses at detection centers, applies Gaussian blur proportional | |
| to average box size, then overlays a JET colormap. | |
| """ | |
| h, w = image.shape[:2] | |
| if not detections: | |
| return image.copy() | |
| # Compute average box dimension for blur sigma | |
| widths = [] | |
| heights = [] | |
| for det in detections: | |
| x1, y1, x2, y2 = det["bbox"] | |
| widths.append(x2 - x1) | |
| heights.append(y2 - y1) | |
| avg_size = (np.mean(widths) + np.mean(heights)) / 2 | |
| sigma = max(int(avg_size * 1.5), 1) | |
| # Kernel size must be odd | |
| ksize = sigma * 6 + 1 | |
| if ksize % 2 == 0: | |
| ksize += 1 | |
| # Place impulses at detection centers | |
| heat = np.zeros((h, w), dtype=np.float32) | |
| for det in detections: | |
| x1, y1, x2, y2 = det["bbox"] | |
| cx = int((x1 + x2) / 2) | |
| cy = int((y1 + y2) / 2) | |
| cx = np.clip(cx, 0, w - 1) | |
| cy = np.clip(cy, 0, h - 1) | |
| heat[cy, cx] += 1.0 | |
| # Gaussian blur to spread the density | |
| heat = cv2.GaussianBlur(heat, (ksize, ksize), sigma) | |
| # Normalize to 0-255 and apply colormap | |
| if heat.max() > 0: | |
| heat = (heat / heat.max() * 255).astype(np.uint8) | |
| else: | |
| heat = heat.astype(np.uint8) | |
| colormap = cv2.applyColorMap(heat, cv2.COLORMAP_JET) | |
| # Blend with original | |
| blended = cv2.addWeighted(image, 0.6, colormap, 0.4, 0) | |
| return blended | |