将二维数组分成更小的数组,获取块均值,并绘制热图
Chunk 2D array into smaller arrays, get the chunk means, and plot a heatmap
我想使用 seaborn 制作热图。我有一个 1920x1080 二维数组,其中包含从 0 到 1 的图像每个像素的显着性值(0 = 最低显着性 - 蓝色,1 = 最高显着性 - 红色)。我已将我的图像分成 80x90 像素的较小网格。我得到下面的图片:
到目前为止一切顺利。我接下来要做的是创建一个 seaborn 热图,这样每个网格都被平均并只用一种颜色表示(蓝色网格代表低显着性区域,暖色网格代表高显着性区域),如下所示:
但是,使用此代码:
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()
我得到这个空图:
如果我注释掉 ax.set_xticks(xticks)
和 ax.set_yticks(yticks)
,我会得到这个:
我在这里错过了什么?
主阵
- 删除
linewidth
- 添加
set_xticklabels
和 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()
划分数组
- 我使用了这个 answer 中的函数将数据分块到一个数组中
(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
- 这是另一个答案中用于重塑数组的函数
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))
我想使用 seaborn 制作热图。我有一个 1920x1080 二维数组,其中包含从 0 到 1 的图像每个像素的显着性值(0 = 最低显着性 - 蓝色,1 = 最高显着性 - 红色)。我已将我的图像分成 80x90 像素的较小网格。我得到下面的图片:
到目前为止一切顺利。我接下来要做的是创建一个 seaborn 热图,这样每个网格都被平均并只用一种颜色表示(蓝色网格代表低显着性区域,暖色网格代表高显着性区域),如下所示:
但是,使用此代码:
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()
我得到这个空图:
ax.set_xticks(xticks)
和 ax.set_yticks(yticks)
,我会得到这个:
我在这里错过了什么?
主阵
- 删除
linewidth
- 添加
set_xticklabels
和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()
划分数组
- 我使用了这个 answer 中的函数将数据分块到一个数组中
(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
- 这是另一个答案中用于重塑数组的函数
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))