Salva array numpy a 16 bit come immagine PNG a 16 bit

Sep 24 2020

Sto cercando di salvare un array numpy a 16 bit come PNG a 16 bit ma quello che ottengo è solo un'immagine nera. Metto qui un minimo esempio di ciò di cui sto parlando.

im = np.random.randint(low=1, high=6536, size=65536).reshape(256,256) #sample numpy array to save as image
plt.imshow(im, cmap=plt.cm.gray)

Dato l'array numpy sopra, questa è l'immagine che vedo con matplotlib, ma quando poi salvo l'immagine come png a 16 bit ottengo l'immagine qui sotto:

import imageio

imageio.imwrite('result.png', im)

Immagine salvata:

dove sono visibili alcuni punti grigio chiaro ma l'immagine è sostanzialmente nera. Comunque quando rileggo l'immagine e la visualizzo di nuovo con matplotlib vedo la stessa immagine iniziale. Ho anche provato altre librerie invece di imageio(come PILo PyPNG) ma con lo stesso risultato.

So che i valori dell'immagine a 16 bit vanno da 0 a 65535 e nell'array numpy qui ci sono solo valori da 1 a 6536, ma ho bisogno di salvare immagini di array numpy simili a questo, cioè dove il valore massimo rappresentato nell'immagine non è è il valore massimo rappresentabile. Penso che una sorta di nornalizzazione sia coinvolta nel processo di salvataggio. Ho bisogno di salvare l'array esattamente come li vedo in matplotlib alla massima risoluzione e senza compressione o restringimento nei loro valori (quindi la divisione per 255 o la conversione in array a 8 bit non sono adatte).

Risposte

2 WarrenWeckesser Sep 24 2020 at 14:38

Sembra che imageio.imwritefarà la cosa giusta se converti il ​​tipo di dati dell'array numpy.uint16prima di scrivere il file PNG:

imageio.imwrite('result.png', im.astype(np.uint16))

Quando lo faccio, result.pngè un file PNG in scala di grigi a 16 bit.

Se si desidera che l'immagine abbia l'intera gamma della scala di grigi dal nero al bianco, sarà necessario ridimensionare i valori all'intervallo [0, 65535]. Ad esempio qualcosa come:

im2 = (65535*(im - im.min())/im.ptp()).astype(np.uint16)

Quindi puoi salvare quell'array con

imageio.imwrite('result2.png', im2)

Per scrivere un array NumPy in un file PNG, un'alternativa è numpngw(un pacchetto che ho creato). Per esempio,

from numpngw import write_png

im2 = (65535*(im - im.min())/im.ptp()).astype(np.uint16)
write_png('result2.png', im2)

Se stai già utilizzando imageio, probabilmente non ci sono vantaggi significativi nell'utilizzo numpngw. Tuttavia, è una dipendenza molto più leggera di imageio--dipende solo da NumPy (nessuna dipendenza da PIL / Pillow e nessuna dipendenza da libpng).