将Numpy数组另存为图像


260

我有一个Numpy数组类型的矩阵。如何将其作为映像写入磁盘?任何格式都可以使用(png,jpeg,bmp ...)。一个重要的约束是不存在PIL。


12
我只想指出以下某些答案,当然还有一些来找这个问题的人,不符合上面列出的没有 PIL的限制。由于一些提问者和一些答案都避免了这种限制,因此,我鼓励所有在这里并且不介意让PIL在下面查看的人,以及任何非PIL答案(新的或旧的)都提及他们是PIL的使用者答案的类型,以区别于满足原始约束的答案。
林德斯(Lindes)2013年

Answers:


54

您可以使用PyPNG。这是一个纯Python(无依赖项)开源PNG编码器/解码器,它支持将NumPy数组写为图像。


4
切记将值缩放到合适的PNG范围,通常为0..255。神经网络中的值范围通常为0..1或-1..1。
托马什Gavenčiak

8
PyPNG是纯Python,可减少其外部依赖关系,但比PIL及其派生类要慢得多。例如,使用PyPNG在计算机上保存3000x4000图像需要4.05秒,而使用scipy.misc.imsave仅需0.59秒(快6倍)。
Zvika '18年

@TomášGavenčiak-较新版本的Scipy中已弃用scipy.misc.imsave。以下是一些替代方法,即使用imageio.imwrite('image_file.jpg',array)
Psi-Ed

258

这使用了PIL,但也许有人会觉得有用:

import scipy.misc
scipy.misc.imsave('outfile.jpg', image_array)

编辑:当前scipy版本开始规范化所有图像,以便min(数据)变为黑色,而max(data)变为白色。如果数据应该是精确的灰度级或精确的RGB通道,则这是不需要的。解决方案:

import scipy.misc
scipy.misc.toimage(image_array, cmin=0.0, cmax=...).save('outfile.jpg')

19
imsave生活在使用PIL的... / scipy / misc / pilutil.py中
denis 2010年

5
转换为jpg时要小心,因为它有损,因此您可能无法恢复用于生成图像的确切数据。
Feanil

8
现在已在scipy 0.19中弃用了此用法-scipy.io.imwrite
g.stevo

6
“ imsave在SciPy 1.0.0中已弃用,并将在1.2.0中删除”(Scipy 1.1.0 doc
noobar

15
scipy.misc.imsave已过时。使用导入图像 imageio.imwrite('file_name.jpg',nmupy_array)
ChaosPredictor

228

使用PIL的答案(以防万一)。

给定一个numpy数组“ A”:

from PIL import Image
im = Image.fromarray(A)
im.save("your_file.jpeg")

您可以用几乎任何所需的格式替换“ jpeg”。有关格式的更多详细信息,请点击此处


5
图像是PIL的模块。做“打印Image .__ file__”
Juh_ 2012年

10
对于我们其中流浪并患有PIL的人非常有帮助-我想我会from PIL import Image保持清楚...
sage 2013年

4
如果你有一个RGB图像,你可以使用IM = Image.fromarray(A).convert(“RGB”)更多信息获得图像stackoverflow.com/questions/4711880/...
罗杰Veciana

使用uint8数组的第三轴编码RGB可以使用此方法。可以使用“ pip install pillow”安装模块PIL。
bli

1
@Ludovico Verniani它不会扭曲图像,但是会使用某种不常见的颜色编码,其中颜色的顺序是BGR而不是RGB。
Zvika

86

matplotlib

import matplotlib

matplotlib.image.imsave('name.png', array)

适用于matplotlib 1.3.1,我不知道较低的版本。从文档字符串:

Arguments:
  *fname*:
    A string containing a path to a filename, or a Python file-like object.
    If *format* is *None* and *fname* is a string, the output
    format is deduced from the extension of the filename.
  *arr*:
    An MxN (luminance), MxNx3 (RGB) or MxNx4 (RGBA) array.

在此处输入图片说明


使用这个。但是遭受内存泄漏的
困扰

较新版本中的matplotlib.imsave()
Vinay Lodha,

6
matplotlib.pyplot.imsave在matplotlib 2+中
Aleksei Petrenko '18

1
@HughPerkins尝试将Pillow替换为Python 3中的PIL
christianbrodbeck

10
import matplotlib.pyplot as plt然后plt.imsave('name.png', array)
Alessandro Jacopson

61

纯Python(2和3),无第三方依赖的代码段。

此函数写入压缩的真彩色(每个像素4个字节)RGBAPNG。

def write_png(buf, width, height):
    """ buf: must be bytes or a bytearray in Python3.x,
        a regular string in Python2.x.
    """
    import zlib, struct

    # reverse the vertical line order and add null bytes at the start
    width_byte_4 = width * 4
    raw_data = b''.join(
        b'\x00' + buf[span:span + width_byte_4]
        for span in range((height - 1) * width_byte_4, -1, - width_byte_4)
    )

    def png_pack(png_tag, data):
        chunk_head = png_tag + data
        return (struct.pack("!I", len(data)) +
                chunk_head +
                struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head)))

    return b''.join([
        b'\x89PNG\r\n\x1a\n',
        png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)),
        png_pack(b'IDAT', zlib.compress(raw_data, 9)),
        png_pack(b'IEND', b'')])

...数据应直接写入以二进制格式打开的文件,如:

data = write_png(buf, 64, 64)
with open("my_image.png", 'wb') as fh:
    fh.write(data)


2
这似乎正是我要的内容,但是您可以添加一些评论吗?我看不到它如何写入文件。您是否必须将输出写入先前打开的文件中?谢谢!
PhilMacKay

1
@PhilMacKay,只需将数据写入二进制文件即可。添加了评论。
ideaman42

1
有人可以指定图像(buf)应该采用的格式吗?它似乎不是一个麻木的数组...
christianbrodbeck

1
@christianmbrodbeck,一个字节数组(RGBARGBA ...)
ideaman42

1
谢谢@ ideasman42。我将这段代码移植到Blender中使用
emackey

57

opencv用于python的文档在此处提供文档)。

import cv2
import numpy as np

cv2.imwrite("filename.png", np.zeros((10,10)))

如果您需要进行除保存以外的更多处理,则很有用。


1
为什么数组大小为10?是什么导致选择本解决方案中使用的10个?
加西德'17

3
@Gathide就像将一些任意的numpy矩阵写入文件的示例。在现实生活中,np.zeros((10,10))用您的形象代替。
Xocoatzin

5
cmap="gray"使用cv2保存图像时,如何添加类似的内容?
莫娜·贾拉勒

@Xocoatzin链接断开?
jtlz2

1
@ jtlz2更新了链接。
Xocoatzin

30

如果您有matplotlib,则可以执行以下操作:

import matplotlib.pyplot as plt
plt.imshow(matrix) #Needs to be in row,col order
plt.savefig(filename)

这将保存绘图(而不是图像本身)。 在此处输入图片说明


10
不,对于pyplot接口,plt.figure()是多余的。另外,如果您还想查看图形窗口,则只需要plt.show()即可。在这种情况下,只需要保存图像文件,因此无需调用show()。
DopplerShift

7
请注意,生成的图像文件将包含matlplotlib图形的轴和灰色区域-而不仅仅是像素数据。
戴夫

1
如果您在远程主机上运行脚本,则在没有图形界面支持的情况下将其缩进去将无法正常工作。
Temak

如果要在笔记本中显示图像,则可以添加以下内容:>>“ from IPython.display import Image”,然后>>“ Image(filename = filename)”
Robert

卸下轴:plt.axis('off')
yakout

15

您可以在Python中使用'skimage'库

例:

from skimage.io import imsave
imsave('Path_to_your_folder/File_name.jpg',your_array)

15

scipy.misc给出有关imsave功能的弃用警告,并建议使用imageio替代功能。

import imageio
imageio.imwrite('image_name.png', img)

12

@ ideasman42的答案的附录:

def saveAsPNG(array, filename):
    import struct
    if any([len(row) != len(array[0]) for row in array]):
        raise ValueError, "Array should have elements of equal size"

                                #First row becomes top row of image.
    flat = []; map(flat.extend, reversed(array))
                                 #Big-endian, unsigned 32-byte integer.
    buf = b''.join([struct.pack('>I', ((0xffFFff & i32)<<8)|(i32>>24) )
                    for i32 in flat])   #Rotate from ARGB to RGBA.

    data = write_png(buf, len(array[0]), len(array))
    f = open(filename, 'wb')
    f.write(data)
    f.close()

因此,您可以执行以下操作:

saveAsPNG([[0xffFF0000, 0xffFFFF00],
           [0xff00aa77, 0xff333333]], 'test_grid.png')

生产test_grid.png

红色,黄色,深水绿色,灰色网格

(透明度也可以通过减少中的高字节来实现0xff。)


8

对于那些希望直接工作的示例:

from PIL import Image
import numpy

w,h = 200,100
img = numpy.zeros((h,w,3),dtype=numpy.uint8) # has to be unsigned bytes

img[:] = (0,0,255) # fill blue

x,y = 40,20
img[y:y+30, x:x+50] = (255,0,0) # 50x30 red box

Image.fromarray(img).convert("RGB").save("art.png") # don't need to convert

另外,如果您想要高质量的jpeg
.save(file, subsampling=0, quality=100)


6

matplotlib svn具有一项新功能,可以将图像保存为图像,而无需保存轴等。如果您不想安装svn(从matplotlib svn中从image.py直接复制,删除了为简洁起见,请使用docstring):

def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None, origin=None):
    from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
    from matplotlib.figure import Figure

    fig = Figure(figsize=arr.shape[::-1], dpi=1, frameon=False)
    canvas = FigureCanvas(fig)
    fig.figimage(arr, cmap=cmap, vmin=vmin, vmax=vmax, origin=origin)
    fig.savefig(fname, dpi=1, format=format)

3

这个世界可能不需要另一个程序包来将numpy数组写入PNG文件,但是对于那些不够用的人,我最近放上了numpngwgithub:

https://github.com/WarrenWeckesser/numpngw

并在pypi上:https ://pypi.python.org/pypi/numpngw/

唯一的外部依赖项是numpy。

这是examples存储库目录中的第一个示例。基本线很简单

write_png('example1.png', img)

imgnumpy数组在哪里。该行之前的所有代码都是import语句和要创建的代码img

import numpy as np
from numpngw import write_png


# Example 1
#
# Create an 8-bit RGB image.

img = np.zeros((80, 128, 3), dtype=np.uint8)

grad = np.linspace(0, 255, img.shape[1])

img[:16, :, :] = 127
img[16:32, :, 0] = grad
img[32:48, :, 1] = grad[::-1]
img[48:64, :, 2] = grad
img[64:, :, :] = 127

write_png('example1.png', img)

这是它创建的PNG文件:

example1.png


我很好奇,您的lib与其他有何不同?它更快吗?有花哨的功能吗?
F Lekschas

一些功能:(1)使用numpy数组。(2)它仅使用python和numpy编写,因此不需要安装C库。(3)它可以创建动画PNG文件。(4)它提供了一个用于将matplotlib动画编写为动画PNG文件的类。
沃伦·韦克瑟

谢谢!我很好奇它在性能方面与stackoverflow.com/a/19174800/981933相比如何,这也是纯python。前一种方法比PIL快2倍以上,后者真棒。没关系,如果那不是您的目标:)
F Lekschas


2

图像是一个Python库,它提供了一个轻松的界面来读取和写入各种图像数据,包括动画图像,视频,体积数据和科学格式。它是跨平台的,可在Python 2.7和3.4+上运行,并且易于安装。

这是灰度图像的示例:

import numpy as np
import imageio

# data is numpy array with grayscale value for each pixel.
data = np.array([70,80,82,72,58,58,60,63,54,58,60,48,89,115,121,119])

# 16 pixels can be converted into square of 4x4 or 2x8 or 8x2
data = data.reshape((4, 4)).astype('uint8')

# save image
imageio.imwrite('pic.jpg', data)

1

如果您已经碰巧已经使用[Py] Qt,则可能对qimage2ndarray感兴趣。从1.4版(刚刚发布)开始,也支持PySide,它将有一个imsave(filename, array)类似于scipy的小功能,但使用Qt而不是PIL。在1.3中,只需使用以下内容:

qImage = array2qimage(image, normalize = False) # create QImage from ndarray
success = qImage.save(filename) # use Qt's image IO functions for saving PNG/JPG/..

(1.4的另一个优点是它是一个纯python解决方案,这使其更加轻巧。)


1.4版本现已发布。:-)(我相应地编辑了答案。)
hans_meine 2014年

1

如果您在python环境Spyder中工作,那么与仅在变量资源管理器中右键单击数组,然后选择“显示图像”选项相比,它变得更加容易。

在此处输入图片说明

这将要求您将图像大多数以PNG格式保存到dsik。

在这种情况下,将不需要PIL库。


1

使用cv2.imwrite

import cv2
assert mat.shape[2] == 1 or mat.shape[2] == 3, 'the third dim should be channel'
cv2.imwrite(path, mat) # note the form of data should be height - width - channel  

0

为了将一个numpy数组另存为图像,U有几种选择:

1)其他最佳:OpenCV

 import cv2   
 cv2.imwrite('file name with extension(like .jpg)', numpy_array)

2)Matplotlib

  from matplotlib import pyplot as plt
  plt.imsave('file name with extension(like .jpg)', numpy_array)

3)PIL

  from PIL import Image
  image = Image.fromarray(numpy_array)
  image.save('file name with extension(like .jpg)')

4)...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.