【问题标题】:How to transform a 3D array correctly to a 2D array so that you can plot it properly?如何将 3D 数组正确转换为 2D 数组以便正确绘制?
【发布时间】:2021-10-30 16:58:58
【问题描述】:

请注意,我也在使用 StandardScaler。我不确定这是否会影响任何事情。我可以尝试为此提供可重现的代码,但也许没有必要。这可能只是一件麻木的事情。

import numpy as np

x = np.random.rand(60,60,1)

现在我们绘制它,以查看图像。

cs = plt.imshow(x)
plt.colorbar()
plt.show()

我们使用 imshow 执行此操作,它确实接受 3D 数组。不过,我们需要使用仅接受 2D 数组的 contourf。

x = x.reshape(1, 60*60)

现在,我想绘制这个,所以我想把它放到(60,60)。但是如果我只是重新整形回(60,60),图像就会失真。

x = x.reshape(60,60)
cs = plt.contourf(x)
plt.colorbar()
plt.show()

我特别要求对其进行重塑,以便 1. 它与第一张图像相同,以及 2. 可以使用 contourf 完成,因为这是唯一可以使用自定义颜色条的功能据我所知。可以看到图像不同,因为每个颜色条上的最大值不同(0.8 vs 1.05)

【问题讨论】:

  • 你为什么使用contourf而不是再次使用imshow
  • 我无法让颜色条与 imshow 一起使用。它只是空白。

标签: python arrays numpy matplotlib


【解决方案1】:

您的问题涉及多个不同的主题,如果更具体一些会有所帮助。

首先,关于形状,我总是尽量避免(手动)重新塑造自己,这很容易出错,并且需要对形状进行硬编码或使用 x.shape 之类的东西来检索它。

在这种情况下,您可以使用以下方法简单地删除多余的“band”维度:
x = np.squeeze(x)

这让 Numpy 完成工作,并保持其他维度不变。

其次,请注意imshowcontourf 具有不同的默认来源。您可以在帖子中看到这一点,因为与另一张图像相比,一张图像是垂直翻转的。如果您在随机数组中引入一些“工件”,这将变得很明显。 如果您想对此进行控制,您可以自己明确定义来源。

最后,contourf 的颜色是通过为两者之间的值指定一个范围(低、高)来获得特定颜色的。这与使用imshow 时更连续的映射相比有些不同。但是您可以将BoundaryNorm 传递给imshow 以使其行为类似于contourf

样本数据:

x = np.random.rand(20, 20, 1)
x[2:8, 2:8] += 0.4
x = np.clip(x, 0, 1)
x = np.squeeze(x)

颜色图和规范化器:

cmap = plt.cm.viridis
bounds = np.linspace(0, 1, 11)
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)

绘制结果:

fig, (ax1, ax2) = plt.subplots(
    1,2, figsize=(10,5), constrained_layout=True, 
    subplot_kw=dict(xticks=[], yticks=[], aspect=1),
)

im = ax1.imshow(x, cmap=cmap, norm=norm, origin='upper')
cb = fig.colorbar(im, ax=ax1, orientation='horizontal', shrink=0.5, spacing='proportional')

cs = ax2.contourf(x, cmap=cmap, norm=norm, levels=bounds, origin='upper')
cb = fig.colorbar(cs, ax=ax2, orientation='horizontal', shrink=0.5, spacing='proportional')

contourf 的插值会稍微“侵蚀”高点和低点,使其看起来对比度/范围略小。

【讨论】:

    【解决方案2】:

    我使用plt.clim(0,1.05) 更改颜色条范围。 这是你的答案吗?

    import numpy as np
    
    x = np.random.rand(60,60,1)
    
    cs = plt.imshow(x)
    plt.colorbar()
    print(x.shape)
    plt.show()
    
    x = x.reshape(1, 60*60)
    
    x = x.reshape(60,60)
    
    cs = plt.imshow(x)
    plt.colorbar()
    plt.clim(0,1.05)
    print(x.shape)
    plt.show()
    

    EDIT 如您在输出 3d 中看到的,2d 形状图相同:

    【讨论】:

    • 你不能使用 imshow,除非你知道如何给它添加一个颜色条。
    • @mmont 什么意思:unless you know how to add a color bar to it 彩条你需要什么。
    • 除非我使用 contourf,否则我无法弄清楚如何制作自定义颜色条。我尝试使用 imshow() 但它不起作用。
    • @mmont,我编辑答案并添加这一行:plt.clim(0,1.05) 用于更改颜色条范围并使用 imshow,这对您有帮助吗?
    【解决方案3】:

    您可以使用:plt.gca().set_aspect(1)

    如果数组不是方形的,或者更通用的方式:plt.gca().set_aspect(x.shape[1]/x.shape[0])

    【讨论】:

    • 这是否允许您使用选定的刻度线自定义颜色条?我只发现我可以使用 contourf() 函数来做到这一点。
    • 另外,您复制了第二张图片,而我们想要获取第一张图片。您可以通过查看颜色条来判断
    • 这是完全独立的,你可以用contourf和colorbar做任何你想做的事情,set_aspect在轴容器上工作
    • 您的问题是“图像失真。如何正确重塑它?”,我想我已经解决了。如果您还有其他问题,请明确说明 ;)
    • 我认为你误解了这个问题。
    猜你喜欢
    • 2019-09-29
    • 1970-01-01
    • 1970-01-01
    • 2022-12-20
    • 1970-01-01
    • 2019-01-19
    • 2019-10-31
    • 1970-01-01
    • 2017-07-26
    相关资源
    最近更新 更多