1

I use matplotlib.pyplot.imsave with argument cmap='gray' to save a 1024x1024 nparrayas a grayscale image, but when I then read the saved image using matplotlib.pyplot.imread, I get a 1024x1024x4 nparray. Why is this?

Here is the code:

import numpy as np
import matplotlib.pyplot as plt

im = np.random.rand(1024, 1024)
print(im.shape)

plt.imsave('test.png', im, cmap='gray')
im = plt.imread('test.png')

print(im.shape)

The documentation for imread states that "The returned array has shape (M, N) for grayscale images." I suppose this raises the question of what exactly is meant by a grayscale image? How are they stored on disk, and how is Matplotlib supposed to know whether to read an image as grayscale, RGB, RGBA, etc. (and why is it being read as an RGBA image in this case)?

  • "I suppose this raises the question of what exactly is meant by a grayscale image? How are they stored on disk" [Did you](https://meta.stackoverflow.com/questions/261592/) try [using a search engine](https://duckduckgo.com/?q=what+is+a+grayscale+image) to understand this? This is not a question about writing code; it is a question about how image formats work. "why is it being read as an RGBA image in this case" Because that's how the data is stored on your computer. It's important to understand how the formats work. – Karl Knechtel Sep 15 '22 at 10:56
  • Think about it this way. If I just type the letters `a` and `b` into a text document over and over - no newlines or anything - will I be able to save the file in a 1-bit-per-character text format? No, because there *isn't one* - at least, certainly not anything *standard*. But there *are* many formats for images. Documentation for image processing libraries generally expects you to understand such fundamentals. – Karl Knechtel Sep 15 '22 at 10:58
  • I have indeed tried using a search engine to understand how images are stored on a computer, and have understood it to the extent that "images are simply just tensors containing pixel values" (and a grayscale image has just one channel), and that different image formats means different ways of compressing these tensors. But in that case my code above should basically just save a matrix, and imread should just read this matrix. "This is not a question about writing code" - Fair enough. I just thought that it had enough relevance for explaining the behaviour of imread/imsave. – user3221037 Sep 15 '22 at 14:44
  • "The documentation for imread states that" Okay; but what about the documentation for `matplotlib.pyplot.imsave`? Did you try using any other techniques to verify the format of the image file, for example, loading it in an image editor, or looking at the first few bytes in a hex editor? – Karl Knechtel Sep 16 '22 at 05:00
  • Kind of a duplicate from this question: [how to save an array as a grayscale image with matplotlib/numpy?](https://stackoverflow.com/questions/26929052/how-to-save-an-array-as-a-grayscale-image-with-matplotlib-numpy). Check my answer [here](https://stackoverflow.com/a/76961612/8682939). – rvimieiro Aug 23 '23 at 13:05

2 Answers2

1

I believe the cmap parameter doesn't change the file structure whatsoever in imsave.

The code from the matplotlib library for this function doesn't seem to take in account cmap for the number of channels it saves the file https://github.com/matplotlib/matplotlib/blob/v3.5.3/lib/matplotlib/image.py#L1566-L1675

PlainRavioli
  • 1,127
  • 1
  • 1
  • 10
1

I also think that Plain Onion's answer is correct. Secondly

Rather than this If you want to save a grayscale image use open cv try this code-

import cv2  
img = cv2.imread("Image path here") 
img = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
cv2.imread("path where you want to save image",img)
Naman
  • 64
  • 9