0

I would like to take an existing dataset of incident rate of viral spread at a specific non-geographic location and create a heatmap based on a set of co-ordinates I will feed it for the base image.

In order to do so I would take an existing image of a site, such as Raccoon City below:

Racoon City

On that, I want to superimpose a heatmap similar to this on top of it as numbers increase in certain areas (like Downtown, Raccoon Park, City College of Raccoon):

fog of war

I've looked at various libraries including OpenCV, and Pillow, but haven't found a well suited solution. I keep seeing references to heatmap.py, but it seems to be totally deprecated; and I can't get it installed with pip.

I can link to a dummy dataset if needed.

Thanks for looking! This might just save us from the imminent zombie apocalypse ( ¬º-°)¬.

HansHirse
  • 18,010
  • 10
  • 38
  • 67
John Conor
  • 722
  • 6
  • 20
  • Post your image and corresponding heat map image. – fmw42 Apr 15 '21 at 23:16
  • I'm not following? I put 2 images in the post. – John Conor Apr 15 '21 at 23:56
  • They are not the same size. So how do I know where to place the heat map over the image? Is it centered? – fmw42 Apr 16 '21 at 00:16
  • Ah... I see. The 2nd image is just an example of what I would like to do. The idea would be a co-ordinate grid would map over the original image and each co-ordinate tuple would contain a value that would increase and decrease with a corresponding colour change. Does that make sense? – John Conor Apr 16 '21 at 00:56
  • Not quite. How are x,y coordinates related to your heat map values? Do you have a function or just some intensity values that you want to use? If the latter are they interpolated over the image or just sparse point locations that would need to be interpolated? – fmw42 Apr 16 '21 at 01:17

1 Answers1

2

Assuming you have 2D (zombie attack) data stored in some NumPy array, I'd use Matplotlib's colormaps to generate a heatmap from the normalized data, cf. this Q&A. Then, I'd blend that heatmap with the (Raccoon City) image. Therefore, it'd be nice to also have some alpha transparency within the colormap, cf. this Q&A.

Here's some code:

import cv2
from matplotlib.colors import ListedColormap    # Needed for custom colormap
from matplotlib.pyplot import cm, Normalize     # Needed for heatmap
import numpy as np
from scipy.stats import multivariate_normal     # Needed for mockup data

# Read image
image = cv2.imread('R42nH.jpg')

# Generate mockup data
h, w = image.shape[:2]
x = np.arange(w)
y = np.arange(h)
X, Y = np.meshgrid(x, y)
pos = np.dstack((X, Y))
mus = [[200, 100], [300, 400], [500, 150]]
covs = [[[300, 155], [175, 550]], [[400, -100], [40, 250]], [[150, 10], [35, 200]]]
zombies = np.zeros((h, w), np.float64)
for mu, cov in zip(mus, covs):
    rv = multivariate_normal(mu, cov)
    Z = rv.pdf(pos)
    zombies += Z / np.max(Z)
zombies /= np.max(zombies)

# Generate custom colormap with alpha channel,
# cf. https://stackoverflow.com/a/37334212/11089932
cmap = cm.autumn_r
c_cmap = cmap(np.arange(cmap.N))
c_cmap[:, -1] = np.linspace(0, 1, cmap.N)
c_cmap = ListedColormap(c_cmap)

# Generate heatmap, cf. https://stackoverflow.com/a/31546410/11089932
norm = Normalize(vmin=zombies.min(), vmax=zombies.max())
heatmap = c_cmap(norm(zombies))

# Blend image with heatmap
heatmap = cv2.cvtColor(np.uint8(heatmap * 255), cv2.COLOR_RGBA2BGRA)
alpha = heatmap[..., 3] / 255
alpha = np.tile(np.expand_dims(alpha, axis=2), [1, 1, 3])
output = (image * (1 - alpha) + heatmap[..., :3] * alpha).astype(np.uint8)

# Output
cv2.imshow('Zombie Attack', output)
cv2.waitKey(0)
cv2.destroyAllWindows()

The heatmap would look like this:

Heatmap

And, the final output like this:

Output

Please check, if you can feed your data to that pipeline, and if the result is what you have in mind.

The linear alpha transparency on the whole colormap might be not that beneficial, if you also want to have "salient" colors even for lower (zombie attack) numbers. Maybe then manually adapt the alpha transparency.

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.9.1
PyCharm:       2021.1
Matplotlib:    3.4.1
NumPy:         1.20.2
OpenCV:        4.5.1
SciPy:         1.6.2
----------------------------------------
HansHirse
  • 18,010
  • 10
  • 38
  • 67