Search code examples
pythonnumpymatplotlibimread

Python: How to save EXACT numpy array data to image using matplotlib.image.imsave()


I observed some strange behavior when saving and loading data using matplotlibs imsave() and imread() functions. The RGB values I save are different to the ones I get when loading the picture back in again.

import numpy as np
from matplotlib import image

s_pic = np.zeros((1, 1, 3))

s_pic[0,0,0] = 0.123
s_pic[0,0,1] = 0.456
s_pic[0,0,2] = 0.789

image.imsave('pic.png', s_pic)

l_pic = image.imread('pic.png')

print(l_pic[0,0,0])
print(l_pic[0,0,1])
print(l_pic[0,0,2])

The output I get is:

0.12156863
0.45490196
0.7882353

Can somebody explain why the RGB values change in this process? I have checked the matplotlib documentation but couldn't find an answer to this question.


Solution

  • Can somebody explain why the RGB values change in this process?

    RGB values are integers in the range 0-255. Your float is interpreted as:

    >>> .123 * 255
    31.365
    >>> int(.123 * 255)
    31
    

    Thirty-one is being written to that pixel. Then the reverse..

    >>>
    >>> 31 / 255
    0.12156862745098039
    >>>
    

    Delving into the source for imsave() the array passed to imsave() is converted to RGBA values using matplotlib.cm.ScalarMappable().to_rgba(bytes=True)

    >>> from matplotlib import cm
    >>> sm = cm.ScalarMappable()
    >>> rgba = sm.to_rgba(s_pic, bytes=True)
    >>> rgba
    array([[[ 31, 116, 201, 255]]], dtype=uint8)
    >>>