【问题标题】:Pyplot imshow not showing square pixels when setting aspect ratio设置纵横比时,Pyplot imshow 不显示方形像素
【发布时间】:2019-01-17 17:32:21
【问题描述】:

我在使用 Pyplot imshow 从名为 data 的 numpy ndarray 绘制图像时遇到了一些麻烦,同时保持其纵横比和方形像素。 ndarray 的形状是 (112, 2182)。这是我正在使用的代码:

import matplotlib as mpl
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np

mpl.use('Agg')

import matplotlib.pyplot as plt

data = np.random.random_sample((112, 2182))
plt.figure(figsize=(25, 3.5))
plt.subplots_adjust(left=0.1, right=0.9)

ax = plt.subplot(111)
plt.axis('off')
plt.title('Title', fontweight='bold', y=1.15)

im = ax.imshow(data)

# Add same-width colorbar to the bottom of the image
divider = make_axes_locatable(ax)
cax = divider.append_axes("bottom", size="25%", pad=0.3)
cbar = plt.colorbar(im, orientation="horizontal", cax=cax)

# Save image
plt.savefig('image.pdf', dpi=1000, format=pdf)

我认为通过使用ndarray 的形状设置纵横比,图像将显示方形像素。但是,图像似乎保持纵横比,但像素不是正方形,正如您在缩放图像中看到的那样(我仍然无法发布图像,抱歉):

zoomed plot
whole plot

这些输出与我在不使用 aspect 参数时使用 im = ax.imshow(data) 时得到的相同。我手动计算了整个图的 y 轴上的像素,其中有 112 个,所以这不是像素分组的问题。关于如何解决这个问题的任何想法?

编辑:我正在绘制的图像还将有一个颜色条和一个标题。此外,我需要能够将其保存为 pdf 文件。我上传的放大图是在 pdf 查看器中放大的图的屏幕截图。

【问题讨论】:

    标签: python matplotlib pixel aspect-ratio imshow


    【解决方案1】:

    如果您使用ax.imshow(data),您将自动获得方形像素。相反,如果您将纵横比设置为 1/"equal" 以外的其他值,那么您将不会得到方形像素。然而,这与问题中观察到的效果无关。

    “缩放图像”中的问题是数据像素的大小是实际屏幕像素的数量级。因此,图像像素的大小可能与屏幕像素一样多。解决这个问题的方法是保存一个图形,使一个图像像素恰好是一个屏幕像素,或者是它的任何倍数。

    在这种情况下,这很简单

    data = np.random.random_sample((2182, 112))
    plt.imsave("filename.png", data)
    

    【讨论】:

    • 我没有提到情节会有标题和颜色条,需要保存为pdf文件。我想这个答案不会起作用,对吗?请查看我的编辑。
    • 好的,您能否提供您感兴趣的实际代码?在问题中,您有一个 25 英寸宽的图形,但该数组的行数比列数多得多。另外plt.axis("off") 并不表示你想要一个标题。
    • 我更正了随机数据的形状,因为行和列被切换了。我读了link,然后你的答案在这里link,但我不完全理解figsizedpippi 如何在imshow 和pdf 中工作。设置dpi=1000 使像素更加方形,但仍然不是完美的方形。关于如何计算 figsizedpi 来解决问题的任何想法?
    • 现在的颜色条让这变得非常困难。所以你需要leftmargin+axessize+space+colorbar+rightmargin = figuresizedpi和axessize = narrayshape,其中n需要是一个整数。垂直方向也一样。问题是边距的单位与图形大小不同。所以会很麻烦。不确定我是否有时间和动力用代码写下来。
    【解决方案2】:

    您需要使用 imshow 选项重新缩放像素:形状和范围:

    import numpy as np
    import matplotlib.pyplot as plt
    
    shape = (112, 2182)
    extent = [0, 112, 0, 2182]
    
    data = np.random.random_sample(shape)
    
    plt.figure(figsize=(5, 3.5))
    
    ax = plt.subplot(111)
    plt.axis('off')
    
    dx = (extent[1] - extent[0]) / shape[1]
    dy = (extent[3] - extent[2]) / shape[0]
    dx_dy = dx/dy
    
    im = ax.imshow(data, extent=extent, aspect=dx_dy)
    plt.show()
    

    【讨论】:

    • 如果我理解你的代码,最后dx_dy == 1,这是aspect的默认值。所以我们可以说你“只是”将extent 参数添加到imshow。我试过你的代码,但对输出没有影响,它保持原样。
    • 在你的情况下 dx_dy = 0.002634671980817975。如果你放大创建的图像,你会得到漂亮的正方形。
    【解决方案3】:

    文档说aspect 参数可能是浮点数或

    'equal':确保纵横比为 1。像素将是正方形的(除非 像素大小在数据坐标中使用 程度)。

    'auto':轴保持固定,调整纵横比 数据适合轴。一般来说,这将导致 非方形像素。

    因此,1.0 的纵横比就是您要寻找的。鉴于您从数组的形状计算出的值,您不会获得上面显示的输出。 正如@ImportanceOfBeingErnest 指出的那样,aspect='equal' 是默认设置,所以它就像

    im = ax.imshow(data)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-27
      • 2013-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-14
      • 2015-01-29
      相关资源
      最近更新 更多