Why jpeg image becomes 2D array after being loaded - python

I have a jpeg image as follows:
Now I want to load this image to do image processing. I use the following code:
from scipy import misc
import numpy as np
im = misc.imread('logo.jpg')
Because the image is a coloured one, I would expect im is a 3D matrix. However, im.shape gives me a 2D matrix:
(150, 150)
I tried another way of loading image as follows:
from PIL import Image
jpgfile = Image.open("logo.jpg")
But jpgfile also has the size of 150x150.
My question is: What's wrong with my code, or my understanding about RGB image is wrong?
Thank you very much.

From the docs here: http://docs.scipy.org/doc/scipy/reference/generated/scipy.misc.imread.html, specify mode='RGB' to get the red, green, blue values. The output appears to default to conversion to a grayscale number.

Related

Why doesn't Matplotlib read image as grayscale?

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 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
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)

Python PIL read/open TIFF is black only

I try to read a TIFF file with pillow/PIL (7.2.0) in Python (3.8.3), e.g. this image.
The resulting file seems to be corrupted:
from PIL import Image
import numpy as np
myimage = Image.open('moon.tif')
myimage.mode
# 'L'
myimage.format
# 'TIFF'
myimage.size
# (358, 537)
# so far all good, but:
np.array(myimage)
# shows only zeros in the array, likewise
np.array(myimage).sum()
# 0
It doesn't seem to be a problem of the conversion to numpy array only, since if I save it to a jpg (myimage.save('moon.jpg')) the resulting jpg image has the appropriate dimensions but is all black, too.
Where did I do wrong or is it a bug?
I am not an expert in coding but i had same problem and found the TIFF file has 4 layers. R, G ,B and Alpha. When you convert it using PIL it is black.
try to view the image as plt.imshow(myimage[:, :, 0])
you could also remove the Alpha layer by saving the read image ( i used plt.imread('image')) and then saving it as image=image[:,:,3]. Now its a RGB image.
I don't know if i answered your question, but i felt this info might be of help.

Image resizing changes color and texture

I'm cutting up a large image in to smaller overlapping patches, and this 500x500x3 gray square is part of the background.
I'm loading the image into numpy, attempting to scale it down by to 100x100x3, and then saving the image using the following code:
import numpy as np
from scipy import misc
import skimage.transform
from matplotlib.image import imread
im = imread(originalPath)
arr = np.array(im)
resized = skimage.transform.resize(arr,(100,100,3))
misc.imsave("resized.tif", resized)
The saved image is the correct size, but becomes purple and pink rather than the original gray.
I've also tried other rescaling methods including
skimage.transform.downscale_local_mean(arr, (5,5,1))
skimage.measure.block_reduce(arr, block_size=(5,5,1), func=np.mean)
and they all produce slightly varying versions of the same purple-ish square.
I have one main question and one side question:
How do I rescale to have a square with accurate colors?
Am I using the correct rescaling method?

convert greyscale image back to vector

I have a list called w (size: 784), which I outputted to a png greyscale image:
import matplotlib.pyplot as plt
tmp = 1/(1+np.exp(-10*w/w.max()))
plt.imshow(tmp.reshape(28,28),cmap="gray")
plt.draw()
plt.savefig("final_weight_vector")
Now I want to read the png image back to be a vector.
The solutions I found so far:
First:
import matplotlib.image as mpimg
img=mpimg.imread('final_weight_vector.png')
but img appears to not be greyscale, because its dimensions turend out to be (600, 800, 4).
Second:
reading the file as RGB and converting to greyscale:
im = Image.open('final_weight_vector.png').convert('LA')
However, I couldn't find how to iterate over im so I have no idea as to what's inside. Further, I am not sure the output of im will have the exact same values as the original w.
Help please?
The problem is that what you saved is probably a plot of the 28x28 image, not the image itself.
To be sure, please preview the image. I bet it is 600x800, not 28x28. I also suppose it contains many additional elements, like axes and padding.
If you want to store your array in a loadable format, you may use numpy.save() (and numpy.load() to load it).
You may also use PIL to save your array as image (e.g. using something similar to: http://code.activestate.com/recipes/577591-conversion-of-pil-image-and-numpy-array/)

Using Matplotlib imshow to show GIF image

I need to show a background to a matplotlib plot using ax.imshow(). The background images that I will be using are GIF-images. Despite having PIL installed, the following code results in an error complaining that the Python Image Library (PIL) is not installed (which it is):
from pylab import imread
im_file = open("test.gif")
im_obj = imread(im_file)
Reading the image using PIL directly works better:
from PIL import Image
import numpy
img = Image.open("test.gif")
img_arr = asarray(img.getdata(), dtype=numpy.uint8)
However, when reshaping the array, the following code does not work:
img_arr = img_arr.reshape(img.size[0], img.size[1], 3) #Note the number 3
The reason is that the actual color information is contained in a color table accessed through img.getcolors() or img.getpalette().
Converting all the images to PNG or another suitable format that results in RGB images when opening them with imread() or Image.open() is not an option. I could convert the images when needed using PIL but I consider that solution ugly. So the question is as follows: Is there a simple and fast (the images are 5000 x 5000 pixels) way to convert the GIF images to RGB (in RAM) so that I can display them using imshow()?
You need to convert the GIF to RGB first:
img = Image.open("test.gif").convert('RGB')
See this question: Get pixel's RGB using PIL

Categories