Issue
I want to make a heatmap using seaborn. I have a 1920x1080 2D array that contains saliency values of each pixel of an image from 0-1 (0=lowest saliency-blue color, 1=highest saliency-red color). I have divided my image into smaller grids of 80x90 pixels. I am getting the image below:
So far so good. What I want to do next is to create a seaborn heatmap, so that each grid is averaged and represented by only one color (with blue grids representing areas of low saliency and warmer grids representing areas of high saliency), like below:
However, using this code:
import numpy as np
plt.figure(figsize= (16,9))
xticklabels=range(0,1920,80)
yticklabels=range(0,1080,90)
xticks[80,160,240,320,400,480,560,640,720,800,880,960,1040,1120,1200,1280,1360,1440,1520,1600,1680,1760,1840,1920]
yticks=[90,180,270,360,450,540,630,720,810,900,990,1080]
normalized_saliency_map=np.random.random((1080,1920))
ax=sns.heatmap(normalized_saliency_map,
cmap='jet',
linewidth=0.5,
xticklabels = xticklabels,
yticklabels = yticklabels)
ax.set_xticks(xticks)
ax.set_yticks(yticks)
plt.title(f'Image: {i}')
plt.show()
I am getting this empty plot:
If I comment out ax.set_xticks(xticks)
and ax.set_yticks(yticks)
, I am getting this:
What am I missing here?
Solution
Main Array
- Remove
linewidth
- Add
set_xticklabels
andset_yticklabels
# test data
np.random.seed(365)
data = np.random.random((1080,1920))
ax = sns.heatmap(data, cmap='jet')
ax.set_xticks(xticks) # this is only the tick location, not the label
ax.set_xticklabels(xticks) # this adds the labels, after setting the ticks
ax.set_yticks(yticks)
ax.set_yticklabels(yticks)
ax.invert_yaxis() # use if desired to swap the direction of the y-axis values
ax.grid(color='k')
plt.show()
Divide the Array
- I used the function in this answer to chunk the data into an array
(288, 90, 80)
# using function from other answer
chunked = blockshaped(data, 90, 80)
# get the means of each chunk and then reshape
means = np.array([v.mean() for v in chunked]).reshape(12, 24)
# plot the chunks
fig, ax = plt.subplots(figsize= (16,9))
p = sns.heatmap(means, cmap='jet', ax=ax)
p.set_xticks(range(25))
p.set_xticklabels([0] + xticks)
p.set_yticks(range(13))
p.set_yticklabels([0] + yticks)
p.invert_yaxis()
p.grid(color='k')
plt.show()
blockshaped
- Here's the function from the other answer for reshapeding the array
def blockshaped(arr, nrows, ncols):
"""
Return an array of shape (n, nrows, ncols) where
n * nrows * ncols = arr.size
If arr is a 2D array, the returned array should look like n subblocks with
each subblock preserving the "physical" layout of arr.
"""
h, w = arr.shape
assert h % nrows == 0, f"{h} rows is not evenly divisible by {nrows}"
assert w % ncols == 0, f"{w} cols is not evenly divisible by {ncols}"
return (arr.reshape(h//nrows, nrows, -1, ncols)
.swapaxes(1,2)
.reshape(-1, nrows, ncols))
Answered By - Trenton McKinney
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.