File size: 1,607 Bytes
f3f6f5d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
"""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