Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving 'float' numpy images

Here is the code I am currently using:

from PIL import Image
import numpy as np

def save_np_img(np_img, path, name):
    """
    To save the image.
    :param np_img: numpy_array type image
    :param path: string type of the existing path where to save the image
    :param name: string type that includes the format (ex:"bob.png")
    :return: numpy array
    """

    assert isinstance(path, str), 'Path of wrong type! (Must be String)'
    assert isinstance(name, str), 'Name of wrong type! (Must be String)'

    im = Image.fromarray(np_img)
    im.save(path + name)

    return np_img

I would like to be able to save images which contain float values, just like I can currently save int valued-images.

I get a TypeError message when I try to save my images which have been transformed through np.divide(img, 255.), and thus when trying to save numpy_arrays which contain floats.

(You can suggest other librairies, too.)

NOTE: The values, when not integers between 0 and 255, are floats between 0 and 1. It is crucial for me to remain as lossless as possible. My initial thought was that I could simply use np.multiply(img, 255) but I wasn't sure if that would lose some precision (nor if it would return integers, actually).

EDIT: Basically, is this method a lossless convertion? That is, if I had a numpy_array of ints, divided it by 255., and then reconverted into ints, am I losing information? If so, how to avoid that?

like image 670
payne Avatar asked Sep 25 '18 04:09

payne


Video Answer


1 Answers

You can save and read back numpy arrays of floats losslessly and natively without any libraries being required:

import numpy as np

# Create 10 random floats in range 0..1 in array "b"
b = np.random.random_sample((10,)).astype(np.float32)

# Save to file
np.save('BunchOfFloats.npy',b)

# Read back into different array "r"
r = np.load('BunchOfFloats.npy')

# Inspect b 
array([0.26565347, 0.7193414 , 0.19435954, 0.58980538, 0.28096624,
   0.88655137, 0.84847042, 0.80156026, 0.94315194, 0.76888901])

# Inspect r
array([0.26565347, 0.7193414 , 0.19435954, 0.58980538, 0.28096624,
   0.88655137, 0.84847042, 0.80156026, 0.94315194, 0.76888901])

Documentation is available here.


Alternatively, as suggested in the comments by @WarrenWekesser you could use a TIFF file which can store floats, and even doubles.

import numpy as np
from tifffile import imsave

# Generate float data
b=np.random.random_sample((768,1024,3)).astype(np.float32)

# Save as TIF - when reading, use "data = imread('file.tif')"
imsave('result.tif',b)

Yet another option is a PFM file, described here and here.

This is a very simple format that you could write and read yourself, and has the benefit that other packages such as ImageMagick and GIMP understand it, so you could save your data as a PFM file and then convert at the command line with ImageMagick to JPEG or PNG for viewing:

magick image.pfm -auto-level result.png
like image 179
Mark Setchell Avatar answered Oct 10 '22 21:10

Mark Setchell