0

I saved an numpy array to an image as follows:

plt.imshow(xNext[0,:,:,0]) #xNext has shape (1,64,25,1)
print(xNext[0,:,:,0].shape) #outputs (64,25)
plt.savefig(os.path.join(root,filename)+'.png')
np.save(os.path.join(root,filename)+'.npy',xNext[0,:,:,0])

How can I obtain the same numpy array back from the .png saved image? Can you also please show me if I had saved as .jpg image?

I've tried the following and works with 3D array (v1) where resulting image close to the original numpy array produced image (original).

image = Image.open(imageFilename) #brings in as 3D array
box = (315,60,500,540)
image = image.crop(box)
image = image.resize((25,64)) #to correct to desired shape
arr = np.asarray(image)
plt.imshow(arr)
plt.savefig('v1.png')
plt.close()

However, when I convert the 3D array to 2D array, the resulting image is different (v1b and v1c).

arr2 = arr[:,:,0]
plt.imshow(arr2)
plt.savefig('v1b.png')
plt.close()
arr3 = np.dot(arr[...,:3],[0.299,0.587,0.11])
plt.imshow(arr3)
plt.savefig('v1c.png')
plt.close()

How can I convert the 3D to 2D correctly? Thanks for your help.

original, v1 (saved from 3D array)

original v1

v1b, v1c (saved from 2D arrays)

v1b v1c

original (with original size)

enter image description here

Justin Wilson
  • 330
  • 3
  • 17

2 Answers2

1

link

 from scipy.misc import imread
 image_data = imread('test.jpg').astype(np.float32)

This should give you the numpy array (I would suggest using imread from scipy)

  • Thank you. This seems to work (I'm still checking). I had to use np.uint8 instead of np.float32 but you wouldn't have known that. Thanks again – Justin Wilson Aug 15 '18 at 04:35
  • This gets me to (64,25,3) but I need just (64,25). I tried using gray = 0.2989 * r + 0.5870 * g + 0.1140 * b but didn't seem to work. – Justin Wilson Aug 15 '18 at 05:41
1

If your objective is to save a numpy array as an image, your approach have a problem. The function plt.savefig saves an image of the plot, not the array. Also transforming an array into an image may carry some precision loss (when converting from float64 or float32 to uint16). That been said, I suggest you use skimage and imageio:

import imageio
import numpy as np

from skimage import img_as_uint

data = np.load('0058_00086_brown_2_recording1.wav.npy')
print("original", data.shape)

img = img_as_uint(data)
imageio.imwrite('image.png', img)
load = imageio.imread('image.png')

print("image", load.shape)

This script loads the data you provided and prints the shape for verification

data = np.load('0058_00086_brown_2_recording1.wav.npy')
print("original", data.shape)

then it transform the data to uint, saves the image as png and loads it:

img = img_as_uint(data)
imageio.imwrite('image.png', img)
load = imageio.imread('image.png')

the output of the script is:

original (64, 25)
image (64, 25)

i.e. the image is loaded with the same shape that data. Some notes:

  • image.png is saved as a grayscale image
  • To save to .jpg just change to imageio.imwrite('image.jpg', img)
  • In the case of .png the absolute average distance from the original image was 3.890e-06 (this can be verified using np.abs(img_as_float(load) - data).sum() / data.size)

Information about skimage and imageio can be found in the respectives websites. More on saving numpy arrays as images can be found in the following answers: [1], [2], [3] and [4].

Dani Mesejo
  • 61,499
  • 6
  • 49
  • 76
  • Thank you very much! This looks great. I'll test it out in the next couple of days and mark as answer and award bounty if it all works out which looks like it should. Thanks again! – Justin Wilson Aug 19 '18 at 00:54