Saving a Numpy array as an image
An answer using PIL (just in case it's useful).
given a numpy array "A":
from PIL import Image
im = Image.fromarray(A)
im.save("your_file.jpeg")
you can replace "jpeg" with almost any format you want. More details about the formats here
This uses PIL, but maybe some might find it useful:
import scipy.misc
scipy.misc.imsave('outfile.jpg', image_array)
EDIT: The current scipy
version started to normalize all images so that min(data) become black and max(data) become white. This is unwanted if the data should be exact grey levels or exact RGB channels. The solution:
import scipy.misc
scipy.misc.toimage(image_array, cmin=0.0, cmax=...).save('outfile.jpg')
With matplotlib
:
import matplotlib
matplotlib.image.imsave('name.png', array)
Works with matplotlib 1.3.1, I don't know about lower version. From the docstring:
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.
There's opencv
for python (documentation here).
import cv2
import numpy as np
img = ... # Your image as a numpy array
cv2.imwrite("filename.png", img)
useful if you need to do more processing other than saving.
Pure Python (2 & 3), a snippet without 3rd party dependencies.
This function writes compressed, true-color (4 bytes per pixel) RGBA
PNG's.
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'')])
... The data should be written directly to a file opened as binary, as in:
data = write_png(buf, 64, 64)
with open("my_image.png", 'wb') as fh:
fh.write(data)
- Original source
- See also: Rust Port from this question.
- Example usage thanks to @Evgeni Sergeev: https://stackoverflow.com/a/21034111/432509