Saving a Numpy array as an image

Multi tool use
Multi tool use


Saving a Numpy array as an image



I have a matrix in the type of a Numpy array. How would I write it to disk it as an image? Any format works (png, jpeg, bmp...). One important constraint is that PIL is not present.





I'd just like to note that some of the answers below, and surely some of the people coming and finding this question, do not meet the constraint listed above of being without PIL. Since some askers and some answers both avoid that constraint, I encourage anyone who's here and doesn't mind having PIL to look below, and any non-PIL answers (new or old) to mention that they're a PIL-is-used type of answer, to distinguish themselves from answers meeting the original constraint.
– lindes
Oct 30 '13 at 15:46




14 Answers
14



You can use PyPNG. It's a pure Python (no dependencies) open source PNG encoder/decoder and it supports writing NumPy arrays as images.





Remember to scale the values to the right range for PNG, usually 0..255. The value ranges in neural networks are frequently 0..1 or -1..1.
– Tomáš Gavenčiak
Mar 31 at 18:49





PyPNG is pure Python, which reduces its external dependencies, but makes it much slower than PIL and its derived classes. For example, saving a 3000x4000 image on my machine took 4.05 seconds with PyPNG but only 0.59 seconds with scipy.misc.imsave (6x faster).
– Zvika
May 2 at 11:25




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:


scipy


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





imsave lives in .../scipy/misc/pilutil.py which uses PIL
– denis
Apr 16 '10 at 9:46





Ah, I was not aware. Thank you for the reference.
– Steve Tjoa
Apr 16 '10 at 18:34





Be careful when converting to jpg since it is lossy and so you may not be able to recover the exact data used to generate the image.
– Feanil
Dec 20 '12 at 15:20





The code gives me the error "'module' object has no attribute 'misc'". Writing import scipy.misc it works.
– matec
Apr 18 '16 at 9:17


import scipy.misc





This is now deprecated in scipy 0.19 use - scipy.io.imwrite
– g.stevo
Apr 19 '17 at 21:56



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





Image is a module of PIL. Do "print Image.__file__"
– Juh_
Sep 17 '12 at 11:21





Very helpful for those of us who wandered here and do have PIL - I think I'll use from PIL import Image to keep it clear...
– sage
Oct 18 '13 at 20:18



from PIL import Image





If you've got an RGB image, you can get the image using im = Image.fromarray(A).convert('RGB') More info: stackoverflow.com/questions/4711880/…
– Roger Veciana
Mar 18 '14 at 14:33





Using third axis of an array of uint8 to code RGB works with this method. Module PIL can be installed using "pip install pillow".
– bli
Aug 16 '17 at 8:16



Pure Python (2 & 3), a snippet without 3rd party dependencies.



This function writes compressed, true-color (4 bytes per pixel) RGBA PNG's.


RGBA


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'x89PNGrnx1an',
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 fd:
fd.write(data)





This seems to be exactly what I'm looking for, but could you add some comments? I don't see how this writes to a file. Do you have to write the output in a previously opened file? Thanks!
– PhilMacKay
Nov 22 '13 at 21:28





@PhilMacKay, the data just has to be written to a binary file. added comment.
– ideasman42
Nov 22 '13 at 23:31





Can someone specify what format the image (buf) is supposed to be in? It does not seem to be a numpy array...
– christianbrodbeck
Apr 2 '14 at 20:28


buf





@christianmbrodbeck, a bytearray (RGBARGBA...)
– ideasman42
Apr 2 '14 at 20:51





Nice piece of code!
– Robotbugs
May 22 '16 at 4:24



With matplotlib:


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.



enter image description here





Using this. But suffering from memory leak
– SolessChong
Aug 20 '14 at 8:31





matplotlib.imsave() in newer versions
– Vinay Lodha
Feb 12 at 14:12





It's matplotlib.pyplot.imsave in matplotlib 2+
– Alexey Petrenko
Feb 17 at 2:36


matplotlib.pyplot.imsave



If you have matplotlib, you can do:


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



This will save the plot (not the images itself).
enter image description here





Befoe imshow, one has to add plt.figure() and plt.show()
– Framester
Aug 16 '11 at 13:38





No, for the pyplot interface, the plt.figure() is superfluous. Also, you only need the plt.show() if you want to see a figure window as well--in this case only saving an image file was desired, so there was no need to call show().
– DopplerShift
Aug 22 '11 at 19:42





Note that the resulting image file will contain the axes and grey area of the matlplotlib figure -- not just the pixel data.
– Dave
Nov 10 '14 at 18:42





will not work if you run you script on remote host, ssh-ing to it without graphical interface support.
– Temak
Dec 18 '15 at 12:54





If you want to show the image in a notebook you can add the following: >>"from IPython.display import Image" and then >>"Image(filename=filename)"
– Robert
Feb 23 '16 at 14:17




There's opencv for python (http://docs.opencv.org/trunk/doc/py_tutorials/py_tutorials.html).


opencv


import cv2
import numpy as np

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



useful if you need to do more processing other than saving.





Why array of size 10? What led to the choice of 10 used in this solution?
– Gathide
May 10 '17 at 7:44





@Gathide Just as an example of writing some arbitrary numpy matrix to file. In real life replace np.zeros((10,10)) with your image.
– Xocoatzin
May 10 '17 at 18:23


np.zeros((10,10))





How can I add something like cmap="gray" for when I save the image using cv2?
– Mona Jalal
Jun 13 '17 at 2:55


cmap="gray"



Addendum to @ideasman42's answer:


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()



So you can do:


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



Producing test_grid.png:


test_grid.png



Grid of red, yellow, dark-aqua, grey



(Transparency also works, by reducing the high byte from 0xff.)


0xff



You can use 'skimage' library in Python



Example:


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



matplotlib svn has a new function to save images as just an image -- no axes etc. it's a very simple function to backport too, if you don't want to install svn (copied straight from image.py in matplotlib svn, removed the docstring for brevity):


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)



The world probably doesn't need yet another package for writing a numpy array to a PNG file, but for those who can't get enough, I recently put up numpngw on github:


numpngw



https://github.com/WarrenWeckesser/numpngw



and on pypi: https://pypi.python.org/pypi/numpngw/



The only external dependency is numpy.



Here's the first example from the examples directory of the repository. The essential line is simply


examples


write_png('example1.png', img)



where img is a numpy array. All the code before that line is import statements and code to create img.


img


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)



Here's the PNG file that it creates:



example1.png





I am curious, how is your lib different from the others? Is it faster? Does it have fancy features?
– F Lekschas
Mar 12 at 4:22





A few features: (1) It uses numpy arrays. (2) It is written using just python and numpy, so it does not require a C library to be installed. (3) It can create animated PNG files. (4) It provides a class for writing matplotlib animations as animated PNG files.
– Warren Weckesser
Mar 12 at 4:29





Thanks! I'd be curious how it compares against stackoverflow.com/a/19174800/981933 in terms of performance which is also pure python. The former method is above 2x faster than PIL, which is pretty awesome. Nevermind if that's not your goal :)
– F Lekschas
Mar 12 at 4:58



If you happen to use [Py]Qt already, you may be interested in qimage2ndarray. Starting with version 1.4 (just released), PySide is supported as well, and there will be a tiny imsave(filename, array) function similar to scipy's, but using Qt instead of PIL. With 1.3, just use something like the following:


imsave(filename, array)


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



(Another advantage of 1.4 is that it is a pure python solution, which makes this even more lightweight.)





The 1.4 release is out now. :-) (I edited the answer accordingly.)
– hans_meine
Aug 20 '14 at 21:03



Assuming you want a grayscale image:


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



If you are working in python environment Spyder, then it cannot get more easier than to just right click the array in variable explorer, and then choose Show Image option.



enter image description here



This will ask you to save image to dsik, mostly in PNG format.



PIL library will not be needed in this case.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

arFj5,jgCfWRzJ4x,P2Q96bzpH2Uj yZy9am7
RP1g6 A,meJzy4Ylhv4x,MW2gXc kNImRfJg5OKOBT V1T738r3rv MgCUBQdWagO,wP 1L6

Popular posts from this blog

Rothschild family

Cinema of Italy