Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving grayscale image using matplotlib and when loading it has multiple channels

I am saving images using

import matplotlib.pyplot as plt
plt.imsave(img_path,img_arr,cmap = 'gray') #shape (512,512)
...
img = plt.imread(img_path)

and the img.shape returns a (512,512,4) whereas i expect it to only be (512,512). I thought maybe all the channels would be the same so I could just pick one but np.allclose(img[:,:,0],img_arr) returns false no matter which index I choose. Printing the images, they are indeed the correct ones I am comparing as they do look almost identical(by eye), but are obviously not exactly identical.

I also tried saving the images with cv2 but that seems to save a black box for some reason. loading them with cv2.imread(img_path,0) does return a (512,512) array but something seems to be lost because again, np.allclose() tells me they're different.

I wanted to know if there is a good way to save grayscale images? Every method I try seems to convert it to RBG or RGBA which is really annoying. Also, I would like to preserve the dtype (int16) of the image as downsampling it loses important information.

Thanks in advance.

like image 997
Ian Benlolo Avatar asked Jul 11 '18 20:07

Ian Benlolo


1 Answers

You cannot preserve a bit depth of 16 bit when saving images with matplotlib with any of the default colormaps which only have 256 colors (=8 bit).

And in addition, matplotlib converts the pixel values to floats, which may be a source for rounding errors.

In total, matplotlib does not seem to be the optimal tool in case you need to get perfect accuracy.

That being said, even PIL does not seem to allow for 16 bit single channel pngs. There is a possible solution in this question, but I haven't tested it.

In any case a bulletproof way to save your array without accuracy loss is to save it with numpy, np.save("arr.npy", im_arr).

like image 164
ImportanceOfBeingErnest Avatar answered Nov 14 '22 23:11

ImportanceOfBeingErnest