将Numpy数组保存为图像

我有一个Numpy数组类型的矩阵。我怎么把它作为映像写到磁盘上呢?任何格式都可以(png, jpeg, bmp…)一个重要的限制是PIL不存在。

829969 次浏览

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

如果你有matplotlib,你可以这样做:

import matplotlib.pyplot as plt
plt.imshow(matrix) #Needs to be in row,col order
plt.savefig(filename)
这将保存情节(而不是图像本身)。 enter image description here < / p >

Matplotlib SVN有一个新函数,可以将图像保存为图像-没有轴等,这是一个非常简单的函数,如果你不想安装SVN(直接从Matplotlib SVN中的image.py复制,为了简洁,删除了文档字符串):

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)

这使用PIL,但是有些人可能会发现它很有用:

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

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

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

使用公益诉讼的答案(以防有用)。

给定一个numpy数组" a ":

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

你可以用几乎任何你想要的格式替换“jpeg”。有关在这里格式的更多详细信息

纯Python (2 &3),一个没有第三方依赖的代码片段。

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

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)

@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中的高字节来工作。)

matplotlib:

import matplotlib.image


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.

enter image description here

如果你碰巧已经在使用[Py]Qt,你可能会对qimage2ndarray感兴趣。从1.4版(刚刚发布)开始,PySide也被支持,并且会有一个类似于scipy的微小imsave(filename, array)函数,但使用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解决方案,这使得它更加轻量级。)

python有opencv (文件在这里)。

import cv2
import numpy as np


img = ... # Your image as a numpy array


cv2.imwrite("filename.png", img)

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

这个世界可能不需要另一个包来将numpy数组写入PNG文件,但对于那些无法满足的人,我最近在github上发布了numpngw:

https://github.com/WarrenWeckesser/numpngw

和在pypi: https://pypi.python.org/pypi/numpngw/

唯一的外部依赖项是numpy。

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

write_png('example1.png', img)

其中img是一个numpy数组。该行之前的所有代码都是导入语句和创建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 .png .

另外,我使用numpngw.write_apng曼哈顿度规中的Voronoi图中创建动画。

假设你想要一张灰度图像:

im = Image.new('L', (width, height))
im.putdata(an_array.flatten().tolist())
im.save("image.tiff")

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

例子:

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

如果你在python环境Spyder中工作,那么它不能比在变量资源管理器中右键单击数组更容易,然后选择显示图像选项。

enter image description here

这将要求您将图像保存到dsik,主要是PNG格式。

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

scipy.misc给出关于imsave函数的弃用警告,并建议使用imageio代替。

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

使用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

对于那些寻找一个直接的充分工作的例子:

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) < / p >

Imageio是一个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)

为了将numpy数组保存为image,你有几个选择:

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)公益诉讼

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

4)……

与pygame

所以这应该是我测试的(如果你没有pygame,你必须安装pygame,使用pip ->PIP安装pygame(有时不工作,所以在这种情况下,你必须下载轮子或STH,但你可以在谷歌上查找)):

import pygame




pygame.init()
win = pygame.display.set_mode((128, 128))
pygame.surfarray.blit_array(win, yourarray)
pygame.display.update()
pygame.image.save(win, 'yourfilename.png')

只要记住根据你的数组改变显示的宽度和高度

这是一个例子,运行这段代码:

import pygame
from numpy import zeros




pygame.init()
win = pygame.display.set_mode((128, 128))
striped = zeros((128, 128, 3))
striped[:] = (255, 0, 0)
striped[:, ::3] = (0, 255, 255)
pygame.surfarray.blit_array(win, striped)
pygame.display.update()
pygame.image.save(win, 'yourfilename.png')

我附加了一个简单的例程来将npy转换为图像。

from PIL import Image
import matplotlib


img = np.load('flair1_slice75.npy')


matplotlib.image.imsave("G1_flair_75.jpeg", img)

下面的答案中有@Nima Farhadi在时间测量方面提出的方法。

最快的是CV2,但重要的是改变颜色顺序从RGB到BGR。简单的是matplotlib。

重要的是要确保数组有unsigned integer format uint8/16/32。

代码:

#Matplotlib
from matplotlib import pyplot as plt
plt.imsave('c_plt.png', c.astype(np.uint8))


#PIL
from PIL import Image
image = Image.fromarray(c.astype(np.uint8))
image.save('c_pil.png')




#CV2, OpenCV
import cv2
cv2.imwrite('c_cv2.png', cv2.cvtColor(c, cv2.COLOR_RGB2BGR))


enter image description here