Home > Software design >  Chunk 2D array into smaller arrays, get the chunk means, and plot a heatmap
Chunk 2D array into smaller arrays, get the chunk means, and plot a heatmap

Time:09-22

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:

enter image description here

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:

enter image description here

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:

enter image description here If I comment out ax.set_xticks(xticks) and ax.set_yticks(yticks), I am getting this:

enter image description here

What am I missing here?

CodePudding user response:

Main Array

  • Remove linewidth
  • Add set_xticklabels and set_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()

enter image description here

Divide the Array

  • I used the function in this enter image description here

    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))
    
  • Related