如何用matplotlib/numpy将数组保存为灰度图像?

svmlkihl  于 12个月前  发布在  其他
关注(0)|答案(5)|浏览(94)

我试图保存一个numpy数组的尺寸为128x128像素到灰度图像。我只是认为pyplot.imsave函数可以完成这项工作,但它不是,它以某种方式将我的数组转换为RGB图像。我试图在转换过程中强制色彩Map表为灰色,但即使保存的图像显示为灰度,它仍然有128x128x4的尺寸。下面是我写的一个代码示例来展示这种行为:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mplimg
from matplotlib import cm

x_tot = 10e-3
nx = 128

x = np.arange(-x_tot/2, x_tot/2, x_tot/nx)

[X, Y] = np.meshgrid(x,x)
R = np.sqrt(X**2 + Y**2)

diam = 5e-3
I = np.exp(-2*(2*R/diam)**4)

plt.figure()
plt.imshow(I, extent = [-x_tot/2, x_tot/2, -x_tot/2, x_tot/2])

print I.shape

plt.imsave('image.png', I)
I2 = plt.imread('image.png')
print I2.shape

mplimg.imsave('image2.png',np.uint8(I), cmap = cm.gray)
testImg = plt.imread('image2.png')
print testImg.shape

在这两种情况下,“print”函数的结果都是(128,128,4)。
谁能解释一下为什么imsave函数会创建这些维度,即使我的输入数组是亮度类型的?当然,有人有办法将阵列保存为标准灰度格式吗?
谢谢你,谢谢

jgzswidk

jgzswidk1#

使用PIL,它应该像这样工作

from PIL import Image

I8 = (((I - I.min()) / (I.max() - I.min())) * 255.9).astype(np.uint8)

img = Image.fromarray(I8)
img.save("file.png")
uqcuzwp8

uqcuzwp82#

还有一种替代方法是使用imageio。它提供了一个简单方便的API,并与Anaconda捆绑在一起。它可以保存灰度图像作为一个单一的颜色通道文件。
引用文档

>>> import imageio
>>> im = imageio.imread('imageio:astronaut.png')
>>> im.shape  # im is a numpy array
(512, 512, 3)
>>> imageio.imwrite('astronaut-gray.jpg', im[:, :, 0])
wgxvkvu9

wgxvkvu93#

也有可能使用scikit-image,那么就不需要将numpy数组转换为PIL对象。

from skimage import io
io.imsave('output.tiff', I.astype(np.uint16))
dced5bon

dced5bon4#

我不想在我的代码中使用PIL,正如问题中提到的,我在使用pyplot时遇到了同样的问题,即使在灰度中,文件也保存在MxNx3矩阵中。
由于磁盘上的实际图像对我来说并不重要,我最终按原样写入矩阵,并使用numpy的保存和load方法阅读它:

np.save("filename", image_matrix)

以及:

np.load("filename.npy")
vaqhlq81

vaqhlq815#

有几种方法可以使用,如其他答案所述。
回答你的问题,对于matplotlib,我的猜测是,对于 .png 文件,他们正在将2D灰度图像转换为RGBA(仍为灰度)3D数组。在matplotlib的GtiHub中看到这一行。这就是为什么你读取的图像是一个3D数组而不是一个2D。
检查下面使用MatplotlibOpencvPillow的最小工作示例。注意,matplotlib也使用pillow,在plt.imread页面上推荐使用它。

import numpy as np
import matplotlib.pyplot as plt
import cv2
import os
from PIL import Image

im = np.random.randint(low=0, high=255, size=(100, 100), dtype=np.uint8)

#### Using matplotlib ####
print("Using matplotlib ------")
print(im.shape)

plt.imsave('test.png', im, cmap='gray', pil_kwargs={'compress_level':0})

print(os.path.getsize('test.png'), 'bytes')

im_r_plt = plt.imread('test.png')

print(im_r_plt.shape)

#### Using PIL ####
print("Using PIL ------")
img = Image.fromarray(im)
img.save('test.png', compress_level=0)

print(os.path.getsize('test.png'), 'bytes')

im_r_pil = Image.open('test.png') 

print(im_r_pil.size)

#### Using opencv ####
print("Using opencv ------")
cv2.imwrite('test.png', im, [cv2.IMWRITE_PNG_COMPRESSION, 0])

print(os.path.getsize('test.png'), 'bytes')

im_r_cv2 = cv2.imread('test.png', cv2.IMREAD_GRAYSCALE)

print(im_r_cv2.shape)

代码输出:

Using matplotlib ------
(100, 100)
40263 bytes
(100, 100, 4)
Using PIL ------
10168 bytes
(100, 100)
Using opencv ------
10180 bytes
(100, 100)

相关问题