【问题标题】:matplotlib plot small image without resamplingmatplotlib 绘制小图像而不重新采样
【发布时间】:2012-04-12 05:09:47
【问题描述】:

我正在尝试使用 matplotlib 在 python 中绘制一个小图像,并希望显示的轴具有与其生成的 numpy 数组相同的形状,即不应重新采样数据。换句话说,数组中的每个条目都应该对应于屏幕上的一个像素(或附近)。这似乎微不足道,但即使在互联网上搜索了一段时间后,我似乎也无法让它工作:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm

X = np.random.rand(30,40)

fig = plt.figure()
fig.add_axes(aspect="equal",extent=[0, X.shape[1], 0, X.shape[0]])
ax = fig.gca()
ax.autoscale_view(True, False, False)
ax.imshow(X, cmap = cm.gray)

plt.show()

【问题讨论】:

  • 看起来您提供的代码可以满足您的要求,矩形 (40x30) 保留在绘制的图像中,并且轴限制与图像形状相匹配。我错过了你的问题吗?
  • 对不起,我的措辞令人困惑。我感兴趣的是类似于 matlab 中的 imshow 功能,其中屏幕上的像素数与矩阵中的条目数匹配,即轴不会重新采样以匹配图形大小。
  • 你的意思是没有插值的图像?如果是这样,只需将您的代码imshow 更改为matshow,或将interpolation = 'nearest' 作为参数添加到imshow 函数。
  • 谢谢,这停止了平滑插值,但我怎样才能减小轴的大小,使图形反映图像的低分辨率?目前它似乎仍在重新调整以匹配图形大小。

标签: python matplotlib


【解决方案1】:

我自己也遇到过同样的问题。如果imshowinterpolation='nearest' 选项不够好,那么如果您的主要目标是在matplotlib 中查看原始、未缩放、未插值、未处理的像素,那么您将无法击败@987654324 @ 恕我直言。演示:

import numpy as np
import numpy.random
import matplotlib.pyplot as plt

a=256*np.random.rand(64,64)

f0=plt.figure()
plt.imshow(a,cmap=plt.gray())
plt.suptitle("imshow")

f1=plt.figure()
plt.figimage(a,cmap=plt.gray())
plt.suptitle("figimage")

plt.show()

当然,这意味着放弃轴(或以某种方式自己绘制)。 figimage 有一些选项可以让您在图形周围移动图像,所以我想可以在其他方式创建的某些轴上操纵它们。

【讨论】:

  • 如果有人想知道,除了 Ipython Notebook 中的图像之外,我能够让 figimage 在没有任何内容的情况下工作的唯一方法是添加一个空的(“关闭”)轴集在 plt.show() 之前,类似于此 S/O 帖子:stackoverflow.com/questions/9295026/…。否则,它只是没有绘制任何东西。
【解决方案2】:

您可以使用以下代码 sn-p 将数组转换为 PIL (Python Imaging Library)。生成的图像将具有与输入数组相同的大小。它可以显示或保存为图像。

from PIL import Image
from numpy import linspace, array, fromfunction, sin, cos
from matplotlib import cm


# scale array between vmin and vmax and encode it to uint8 (256 values)
def scale(arr, vmin, vmax):
    return (255*(arr - vmin)/(vmax - vmin)).clip(0, 255).astype('uint8')

# convert a matplotlib colormap into a PIL palette
def getpalette(cmap):
    return (255.*array(map(lambda x: cmap(x)[0:3], linspace(0., 1.,256))).ravel()).astype('int')


# a sample array
data = fromfunction(lambda i,j: cos((i+j)/50)*sin(i/50.), (200, 300), dtype='float')

# convert the float array to a PIL image
im = Image.fromarray(scale(data, 0, 1))
im.putpalette(getpalette(cm.jet))
im.save('test.png') # or im.show()

唯一的问题是 im.show() 不是很好,因为它需要有图像查看器xv 并且它会写入一个临时图像。因此,您也可以编写一个文件并使用您喜欢的图像查看器加载它。

【讨论】:

    【解决方案3】:

    我不确定我是否完全理解您的问题。这是否意味着您想要 0 和 X.shape[1] 之间的 x 轴和 0 和 X.shape[0] 之间的 y 轴?在这种情况下,这段代码应该可以解决问题:

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.cm as cm
    
    X = np.random.rand(30,40)
    
    fig = plt.figure()
    
    plt.xlim(0, X.shape[1])
    plt.ylim(0, X.shape[0])
    
    ax = fig.gca()
    ax.autoscale_view(True, False, False)
    ax.imshow(X, cmap = cm.gray)
    
    plt.show()
    

    希望对你有帮助

    【讨论】:

    • 谢谢,如果我的问题令人困惑,我很抱歉。我正在尝试在 Matlab 中执行类似 imshow 的操作,其中图中的轴与数组的大小相同,例如屏幕上的每个像素对应于矩阵中的一个条目。以上对数组进行重新缩放和重新采样以匹配图形大小。
    • 我刚刚在stackoverflow上找到了一个类似的帖子,他们使用imshow的插值参数: ax.imshow(X, cmap = cm.gray, extent=(0, X.shape[1], 0 , X.shape[0]), interpolation='nearest') 这里是链接stackoverflow.com/questions/6323737/…
    • 谢谢,使用最近邻插值很好,但我也希望轴更小,即它更能反映数组的真实大小。目前,轴似乎仍在重新缩放以匹配图形大小。
    【解决方案4】:

    如果您知道图像的原始分辨率,则可以在plt.figure(dpi=value) 中将 dpi 参数设置为您想要的。

    您可以在link 上找到有关调整图像大小的更多信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      • 2014-04-29
      • 1970-01-01
      • 2016-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多