将 Numpy 数组保存为图像
- 2024-12-30 08:41:00
- admin 原创
- 56
问题描述:
我有一个 Numpy 数组类型的矩阵。我该如何将其作为图像写入磁盘?任何格式都可以(png、jpeg、bmp……)。一个重要的限制是不存在 PIL。
解决方案 1:
使用PIL
,通过执行以下操作保存 NumPy 数组arr
:
from PIL import Image
im = Image.fromarray(arr)
im.save("your_file.jpeg")
查看文档了解可用的数据格式,包括 JPEG、PNG 等。
解决方案 2:
这使用了 PIL,但也许有些人会发现它很有用:
import scipy.misc
scipy.misc.imsave('outfile.jpg', image_array)
编辑:当前scipy
版本开始对所有图像进行标准化,以便最小(数据)变为黑色,最大(数据)变为白色。如果数据应该是精确的灰度级或精确的 RGB 通道,则这是不必要的。解决方案:
import scipy.misc
scipy.misc.toimage(image_array, cmin=0.0, cmax=...).save('outfile.jpg')
解决方案 3:
和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.
解决方案 4:
这是opencv
适用于 python 的版本(文档在此处)。
import cv2
import numpy as np
img = ... # Your image as a numpy array
cv2.imwrite("filename.png", img)
如果您需要进行除了保存之外的更多处理,这很有用。
解决方案 5:
纯 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
x1a
',
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)
原始来源
另请参阅:该问题中的 Rust Port。
感谢@Evgeni Sergeev 提供的示例用法:https://stackoverflow.com/a/21034111/432509
解决方案 6:
您可以使用PyPNG。它是一个纯 Python(无依赖项)开源 PNG 编码器/解码器,它支持将 NumPy 数组写入图像。
解决方案 7:
要将 numpy 数组保存为图像,您有几种选择:
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)...
解决方案 8:
如果你有 matplotlib,你可以执行以下操作:
import matplotlib.pyplot as plt
plt.imshow(matrix) #Needs to be in row,col order
plt.savefig(filename)
这将保存情节(而不是图像本身)。
解决方案 9:
scipy.misc
给出关于函数的弃用警告imsave
并建议使用imageio
。
import imageio
imageio.imwrite('image_name.png', img)
解决方案 10:
您可以使用 Python 中的“skimage”库
例子:
from skimage.io import imsave
imsave('Path_to_your_folder/File_name.jpg',your_array)
解决方案 11:
@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
。)
解决方案 12:
对于那些寻找直接且完整工作示例的人来说:
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)
解决方案 13:
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)
解决方案 14:
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)
解决方案 15:
这个世界可能不需要另一个将 numpy 数组写入 PNG 文件的包,但是对于那些还不够的人来说,我最近numpngw
在 github 上发布了一个:
https://github.com/WarrenWeckesser/numpngw
在 pypi 上: https: //pypi.python.org/pypi/numpngw/
唯一的外部依赖是 numpy。
这是存储库目录中的第一个示例examples
。关键行很简单
write_png('example1.png', img)
其中img
是 numpy 数组。该行之前的所有代码都是 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 文件:
另外,我还曾经在曼哈顿度量中的 Voronoi 图numpngw.write_apng
中创建动画。
解决方案 16:
假设您想要一张灰度图像:
im = Image.new('L', (width, height))
im.putdata(an_array.flatten().tolist())
im.save("image.tiff")
解决方案 17:
以下答案中包含@Nima Farhadi 在时间测量方面提出的方法。
最快的是 CV2,但将颜色顺序从 RGB 更改为 BGR 很重要。最简单的是 matplotlib。
重要的是确保数组具有无符号整数格式 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))
解决方案 18:
如果您碰巧已经使用过 [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 解决方案,这使得它更加轻量级。)
解决方案 19:
使用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
解决方案 20:
如果您在 python 环境 Spyder 中工作,那么最简单的方法是右键单击变量资源管理器中的数组,然后选择“显示图像”选项。
这将要求您将图像保存到 dsik,大多数为 PNG 格式。
在这种情况下不需要 PIL 库。
解决方案 21:
使用 pygame
所以这应该可以像我测试的那样工作(如果你没有 pygame,那么你必须安装 pygame,使用 pip -> pip install pygame 安装它(这有时不起作用,所以在这种情况下你必须下载 wheel 或其他东西,但你可以在谷歌上查找)):
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')
解决方案 22:
我附加了一个将 npy 转换为图像的简单例程。
from PIL import Image
import matplotlib
img = np.load('flair1_slice75.npy')
matplotlib.image.imsave("G1_flair_75.jpeg", img)
解决方案 23:
您可以使用此代码通过 PIL python 库将您的 Npy 数据转换为图像,因为这个库主要处理图像,在这里,我使用 numpy 在数据集上下文中加载图像格式:
#importing the libraries
from PIL import Image
import numpy as np
data = np.load('/kaggle/input/objects-dataset/nmbu.npy')
im = Image.fromarray(data, 'RGB')
#saving the image from the npy format
im.save("your_file.jpeg")
解决方案 24:
基于@ideasman42的回答和Evgeni Sergeev的附录,这里是一个将numpy数组转换为图像的实现。
注意:此实现将a[1,1,:]
图像放在左上角
为了揭开 png 格式的神秘面纱,我从http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html粘贴了一些信息
此实现显示:
使用调色板并缩放值的 nxm 数组
nxmx3 RGB 数组,具有一种透明颜色;忽略调色板
nxmx4 RGBA 数组;忽略调色板和透明颜色
它返回一个可以传递给 PhotoImage 的字节字符串。它不像下面 Warren Weckesser 写的那样严格,但它以透明的方式将数据传入 tkinter。
# https://stackoverflow.com/questions/902761/saving-a-numpy-array-as-an-image
# http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
# we insist on
# o values between 0-1
# o g, ga, rgb, rgba
# o nxmx 1/2/3/3
import numpy as np
import zlib, struct
def topngbytes(a:np.ndarray,transparentcolor=[1,2,3],hicolor=[255,95,0]):
sz = a.shape
lensz=len(sz)
height,width=sz[0:2]
colortype=0
palette=None
# Color Allowed Interpretation
# Type Bit Depths
#
# 0 1,2,4,8,16 Each pixel is a grayscale sample.
# 2 8,16 Each pixel is an R,G,B triple.
# 3 1,2,4,8 Each pixel is a palette index;
# a PLTE chunk must appear.
# 4 8,16 Each pixel is a grayscale sample,
# followed by an alpha sample.
# 6 8,16 Each pixel is an R,G,B triple,
# followed by an alpha sample.
if lensz==2:
colortype=3 # 8bit palette
amin=np.min(a)
da=np.max(a)-amin
if da==0: a=a*0+127
elif da<72 or da>255: a=255/da*(a-amin)
cmin = np.array(transparentcolor,dtype=float) # generate a two tone palette
dc = hicolor - cmin
palette = np.zeros(shape=(256, 3), dtype=np.uint8)
for i, r in enumerate(palette): r[:] = cmin + dc/255. * i
elif lensz==3:
n=sz[-1] #color info always the last dimension
if n==2: colortype=4 # grey+alpha
elif n==3: colortype=2 # rgb
elif n==4: colortype=6 # rgba
else: raise(ValueError(f"mImg: color dimension must be nxmx 1,2,3 or 4, not {sz}"))
buf = b''.join( b'x00' + row.tobytes() for row in a.astype(dtype=np.uint8))
def png_pack(png_tag, data):
chunk_head = png_tag + data
return struct.pack("!I", len(data)) + \n chunk_head + \n struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head))
# first chunc is IHDR
# Width: 4 bytes
# Height: 4 bytes
# Bit depth: 1 byte --> we use 8 = 0-255
# Color type: 1 byte
# Compression method: 1 byte
# Filter method: 1 byte
# Interlace method: 1 byte
# The PLTE chunk contains from 1 to 256 palette entries, each a three-byte series of the form:
#
# Red: 1 byte (0 = black, 255 = red)
# Green: 1 byte (0 = black, 255 = green)
# Blue: 1 byte (0 = black, 255 = blue)
# The number of entries is determined from the chunk length. A chunk length not divisible by 3 is an error.
#
# This chunk must appear for color type 3, and can appear for color types 2 and 6;
# it must not appear for color types 0 and 4. If this chunk does appear, it must precede the first IDAT chunk.
# There must not be more than one PLTE chunk.
#
# For color type 3 (indexed color), the PLTE chunk is required.
# The first entry in PLTE is referenced by pixel value 0
IHDR=png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, colortype, 0, 0, 0))
PLTE = b'' if (colortype in [0,4]) or palette is None else png_pack(b'PLTE',palette.tobytes())
t=transparentcolor
tRNS = png_pack(b'tRNS', struct.pack("!6B", t[0], 0, t[1], 0, t[2], 0))
IDAT = png_pack(b'IDAT', zlib.compress(buf, 9))
IEND = png_pack(b'IEND', b'')
return b''.join([b'x89PNG
x1a
',IHDR,PLTE,tRNS,IDAT,IEND])
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理必备:盘点2024年13款好用的项目管理软件