Salvataggio di un array Numpy come immagine


261

Ho una matrice nel tipo di un array Numpy. Come lo scriverei su disco come immagine? Qualsiasi formato funziona (png, jpeg, bmp ...). Un vincolo importante è che il PIL non è presente.


12
Vorrei solo notare che alcune delle risposte di seguito, e sicuramente alcune delle persone che vengono e trovano questa domanda, non soddisfano il vincolo sopra elencato di essere senza PIL . Dal momento che alcuni richiedenti e alcune risposte evitano entrambi questo vincolo, incoraggio chiunque sia qui e non dispiaccia avere il PIL a guardare sotto, e qualsiasi risposta non PIL (nuova o vecchia) per menzionare che sono un PIL-è-usato tipo di risposta, per distinguersi dalle risposte che soddisfano il vincolo originale.
lindes

Risposte:


54

Puoi usare PyPNG . È un codificatore / decodificatore PNG open source Python puro (senza dipendenze) e supporta la scrittura di array NumPy come immagini.


4
Ricorda di ridimensionare i valori nell'intervallo corretto per PNG, in genere 0..255. Gli intervalli di valori nelle reti neurali sono spesso 0..1 o -1..1.
Tomáš Gavenčiak,

8
PyPNG è Python puro, che riduce le sue dipendenze esterne, ma lo rende molto più lento di PIL e delle sue classi derivate. Ad esempio, il salvataggio di un'immagine 3000x4000 sulla mia macchina ha richiesto 4,05 secondi con PyPNG ma solo 0,59 secondi con scipy.misc.imsave (6 volte più veloce).
Zvika,

@ TomášGavenčiak - scipy.misc.imsave è ora obsoleto nelle versioni più recenti di Scipy. Un'alternativa di alcuni commenti qui sotto è usare imageio.imwrite ('image_file.jpg', array)
Psi-Ed

259

Questo utilizza PIL, ma forse alcuni potrebbero trovarlo utile:

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

EDIT : la scipyversione corrente ha iniziato a normalizzare tutte le immagini in modo che min (dati) diventino neri e max (dati) diventino bianchi. Ciò è indesiderato se i dati devono essere livelli di grigio esatti o canali RGB esatti. La soluzione:

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

19
imsave vive in ... / scipy / misc / pilutil.py che utilizza PIL
denis

5
Fai attenzione quando esegui la conversione in jpg poiché è in perdita e quindi potresti non essere in grado di recuperare i dati esatti utilizzati per generare l'immagine.
Feanil,

8
Questo è ora deprecato in scipy 0.19 use - scipy.io.imwrite
g.stevo

6
"imsave è deprecato in SciPy 1.0.0 e verrà rimosso in 1.2.0" ( Scipy 1.1.0 doc )
noobar,

15
scipy.misc.imsave è obsoleto. usa import imageio; imageio.imwrite ('nome_file.jpg', nmupy_array)
ChaosPredictor

228

Una risposta usando PIL (nel caso sia utile).

dato un array intorpidito "A":

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

puoi sostituire "jpeg" con quasi tutti i formati che desideri. Maggiori dettagli sui formati qui


5
L'immagine è un modulo di PIL. Esegui "stampa immagine .__ file__"
Juh_

10
Molto utile per quelli di noi che hanno vagato qui e hanno PIL - Penso che userò from PIL import Imageper tenerlo chiaro ...
saggio

4
Se hai un'immagine RGB, puoi ottenere l'immagine usando im = Image.fromarray (A) .convert ('RGB') Altre informazioni: stackoverflow.com/questions/4711880/…
Roger Veciana

L'uso del terzo asse di una matrice di uint8 per codificare RGB funziona con questo metodo. Il modulo PIL può essere installato utilizzando "pip install pillow".
Bla

1
@Ludovico Verniani Non distorce le immagini, ma utilizza una codifica cromatica piuttosto insolita in cui l'ordine dei colori è BGR piuttosto che RGB.
Zvika,

88

Con matplotlib:

import matplotlib

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

Funziona con matplotlib 1.3.1, non conosco la versione precedente. Dalla dotstring:

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.

inserisci qui la descrizione dell'immagine


Usando questo Ma soffre di perdita di memoria
SolessChong

matplotlib.imsave () nelle versioni più recenti
Vinay Lodha,

6
È matplotlib.pyplot.imsavein matplotlib 2+
Aleksei Petrenko il

1
@HughPerkins prova Pillow come sostituto del PIL in Python 3
christianbrodbeck

10
import matplotlib.pyplot as plte poiplt.imsave('name.png', array)
Alessandro Jacopson il

62

Pure Python (2 e 3), uno snippet senza dipendenze di terze parti.

Questa funzione scrive RGBAPNG compressi a colori reali (4 byte per pixel) .

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'')])

... I dati devono essere scritti direttamente in un file aperto come binario, come in:

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


2
Questo sembra essere esattamente quello che sto cercando, ma potresti aggiungere qualche commento? Non vedo come questo scrive su un file. Devi scrivere l'output in un file precedentemente aperto? Grazie!
PhilMacKay,

1
@PhilMacKay, i dati devono solo essere scritti in un file binario. commento aggiunto.
ideasman42

1
Qualcuno può specificare in quale formato bufdovrebbe essere l'immagine ( )? Non sembra essere un array insensibile ...
christianbrodbeck

1
@christianmbrodbeck, a bytearray (RGBARGBA ...)
ideasman42

1
Grazie @ ideasman42. Ho portato questo codice per l'uso in Blender .
Emackey,

57

C'è opencvper Python ( documentazione qui ).

import cv2
import numpy as np

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

utile se è necessario eseguire più elaborazioni oltre al salvataggio.


1
Perché matrice di dimensioni 10? Cosa ha portato alla scelta di 10 utilizzati in questa soluzione?
Gathide,

3
@Gathide Proprio come un esempio di scrittura di una matrice numpy arbitraria su file. Nella vita reale sostituisci np.zeros((10,10))con la tua immagine.
Xocoatzin,

5
Come posso aggiungere qualcosa di simile cmap="gray"per quando salvo l'immagine usando cv2?
Mona Jalal,

@Xocoatzin Link rotto?
jtlz2

1
@ jtlz2 Link aggiornato.
Xocoatzin,

30

Se hai matplotlib, puoi fare:

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

Ciò salverà la trama (non le immagini stesse). inserisci qui la descrizione dell'immagine


10
No, per l'interfaccia pyplot, plt.figure () è superfluo. Inoltre, è necessario solo plt.show () se si desidera vedere anche una finestra di figura - in questo caso è stato richiesto solo il salvataggio di un file di immagine, quindi non è stato necessario chiamare show ().
DopplerShift

7
Si noti che il file di immagine risultante conterrà gli assi e l'area grigia della figura matlplotlib, non solo i dati pixel.
Dave,

1
non funzionerà se si esegue lo script sull'host remoto, utilizzando la stessa senza il supporto dell'interfaccia grafica.
Temak,

Se vuoi mostrare l'immagine in un taccuino puoi aggiungere quanto segue: >> "da IPython.display import Image" e poi >> "Image (nome file = nome file)"
Robert

Per rimuovere l'asse:plt.axis('off')
yakout il

15

Puoi usare la libreria 'skimage' in Python

Esempio:

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

15

scipy.miscfornisce un avviso di deprecazione sulla imsavefunzione e suggerisce l'utilizzo di imageioinvece.

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

12

Addendum alla risposta di @ 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()

Quindi puoi fare:

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

Produzione test_grid.png:

Griglia di rosso, giallo, verde acqua, grigio

(La trasparenza funziona anche, riducendo il byte alto da 0xff.)


8

Per chi cerca un esempio diretto e perfettamente funzionante:

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

inoltre, se si desidera jpeg di alta qualità
.save(file, subsampling=0, quality=100)


6

matplotlib svn ha una nuova funzione per salvare le immagini come una sola immagine - niente assi ecc. è anche una funzione molto semplice per eseguire il backport, se non si desidera installare svn (copiato direttamente da image.py in matplotlib svn, rimosso il documentazione per brevità):

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

Il mondo probabilmente non ha bisogno di un altro pacchetto per scrivere un array numpy in un file PNG, ma per quelli che non ne hanno abbastanza, di recente ho messo numpngwsu github:

https://github.com/WarrenWeckesser/numpngw

e su pypi: https://pypi.python.org/pypi/numpngw/

L'unica dipendenza esterna è intorpidita.

Ecco il primo esempio dalla examplesdirectory del repository. La linea essenziale è semplicemente

write_png('example1.png', img)

dove imgè un array intorpidito. Tutto il codice prima di quella riga è costituito da istruzioni di importazione e codice da creare 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)

Ecco il file PNG che crea:

example1.png


Sono curioso, in che modo la tua lib è diversa dalle altre? È più veloce? Ha caratteristiche fantasiose?
F Lekschas,

Alcune caratteristiche: (1) Usa array intorpiditi. (2) È scritto usando solo Python e Numpy, quindi non richiede l'installazione di una libreria C. (3) Può creare file PNG animati. (4) Fornisce una classe per la scrittura di animazioni matplotlib come file PNG animati.
Warren Weckesser,

Grazie! Sarei curioso di come si confronta con stackoverflow.com/a/19174800/981933 in termini di prestazioni che è anche puro pitone. Il primo metodo è molto più veloce di 2 volte rispetto a PIL, il che è davvero fantastico. Non importa se questo non è il tuo obiettivo :)
F Lekschas

2

Supponendo che desideri un'immagine in scala di grigi:

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

2

Imageio è una libreria Python che fornisce un'interfaccia semplice per leggere e scrivere una vasta gamma di dati di immagini, tra cui immagini animate, video, dati volumetrici e formati scientifici. È multipiattaforma, funziona su Python 2.7 e 3.4+ ed è facile da installare.

Questo è un esempio per l'immagine in scala di grigi:

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

Se usi già [Py] Qt, potresti essere interessato a qimage2ndarray . A partire dalla versione 1.4 (appena rilasciata), è supportato anche PySide e ci sarà una piccola imsave(filename, array)funzione simile a Scipy, ma usando Qt invece di PIL. Con 1.3, basta usare qualcosa di simile al seguente:

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

(Un altro vantaggio di 1.4 è che si tratta di una soluzione in puro pitone, che lo rende ancora più leggero.)


La versione 1.4 è ora disponibile. :-) (Ho modificato la risposta di conseguenza.)
hans_meine

1

Se lavori in ambiente Python Spyder, non può essere più semplice che fare semplicemente clic con il pulsante destro del mouse sull'array in Esplora risorse, quindi scegliere l'opzione Mostra immagine.

inserisci qui la descrizione dell'immagine

Questo ti chiederà di salvare l'immagine su dsik, principalmente in formato PNG.

In questo caso la libreria PIL non sarà necessaria.


1

Usa 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  

1

per salvare una matrice numpy come immagine, U ha diverse scelte:

1) il meglio dell'altro: 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) ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.