简体   繁体   中英

Save 16-bit numpy arrays as 16-bit PNG image

I'm trying to save a 16-bit numpy array as a 16-bit PNG but what I obtain is only a black picture. I put here a minimum example of what I'm talking aboout.

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)

在此处输入图片说明

Given the above numpy array this is the image I see with matplotlib, but when then I save the image as 16-bit png I obtain the picture below:

import imageio

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

Image saved:

在此处输入图片说明

where some light grey spots are visible but the image is substantially black. Anyway when I read back the image and visualize it again with matplotlib I see the same starting image. I also tried other libraries instead of imageio (like PIL or PyPNG ) but with the same result.

I know that 16-bit image values range from 0 to 65535 and in the array numpy array here there only values from 1 to 6536, but I need to save numpy arrays images similar to this, ie where the maximum value represented in the image isn't the maximum representable value. I think that some sort of nornalization is involved in the saving process. I need to save the array exactly as I see them in matplotlib at their maximum resolution and without compression or shrinkage in their values (so division by 255 or conversion to 8-bit array are not suitable).

It looks like imageio.imwrite will do the right thing if you convert the data type of the array to numpy.uint16 before writing the PNG file:

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

When I do that, result.png is a 16 bit gray-scale PNG file.

If you want the image to have the full grayscale range from black to white, you'll have to scale the values to the range [0, 65535]. Eg something like:

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

Then you can save that array with

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

For writing a NumPy array to a PNG file, an alternative is numpngw (a package that I created). For example,

from numpngw import write_png

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

If you are already using imageio , there is probably no signficant advantage to using numpngw . It is, however, a much lighter dependency than imageio --it depends only on NumPy (no dependence on PIL/Pillow and no dependence on libpng ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM