Numpy ignoring frames of TIF file when converting from PIL - python

I have 3 diemnsional image saved as a multi page tif file. I tried reading it in using PIL(low) and it detected the correct number of frames but when I convert it to numpy it ignores the frames and only converts the single page/layer.
from PIL import Image
import numpy as np
pil_ = Image.open(path)
pil_.size # this outputs (1024, 512)
pil_.n_frames # this outputs the correct number of frames i.e. 21
num = np.array(pil_)
num.shape # this outputs (512, 1024)
Shouldnt the numpy array be a 3D array? How do I convert it so that the frames are also considered?
Thanks

There's a thread here (https://mail.python.org/pipermail/python-list/2007-May/419217.html) which suggests that you may be able to manually seek through the frames and assign each one into the 3rd dimension of your numpy array.

Related

How can I take generate mean image of many 32x32 grayscale images in Python?

I have array are which is 50000x32x32. arr[i] stores the i-th grayscale image.
I want to compute the mean image of these images. I tried the following code(I got this code from stack overflow itself). This code was actually meant for RGB images.
I know, these changes of mine have a lot of mistakes, Apologies.
import os, numpy, PIL
from PIL import Image
# Access all PNG files in directory
allfiles=os.listdir(os.getcwd())
imlist=arr
N=len(imlist)
# Assuming all images are the same size, get dimensions of first image
w,h=Image.fromarray(imlist[0]).size
# Create a numpy array of floats to store the average (assume RGB images)
brr=numpy.zeros((h,w),numpy.float)
# Build up average pixel intensities, casting each image as an array of floats
for im in imlist:
imarr=numpy.array(Image.fromarray(im),dtype=numpy.float)
brr=brr+imarr/N
# Round values in array and cast as 8-bit integer
brr=numpy.array(numpy.round(arr),dtype=numpy.uint8)
# Generate, save and preview final image
out=Image.fromarray(brr,mode="L")
out.save("Average.png")
out.show()
Once you have your 5000 × 32 × 32 array, you can compute the mean image by using np.mean() with axis=0 (the first axis, which contains the collection of images). Let's make some random data:
import numpy as np
images = np.random.random((5000, 32, 32))
Now we can compute the mean image:
mean_image = images.mean(axis=0)
We can look at it with:
import matplotlib.pyplot as plt
plt.imshow(mean_image)
Which looks something like:

(Loading .mat file as image in OpenCV) - Reshaping numpy array with 128 channels to 3 channels

I am trying to load .mat image exported from Tensorflow with Scipy.io using OpenCV.
I can modify the Tensorflow code to export the .mat image with only 3 channels directly but I will lose a lot of data and it doesn't look correct even.
And that's why I am trying to export the raw data as it is.
In my case I load the .mat file with scipy.io and get the numpy array which looks like this
(640, 640, 128)
and I want to reshape it because OpenCV cannot load an image with 128 channels.
(640, 640, 3)
I am not fully understanding the concept of reshaping and I think I am doing it wrong.
I am getting this error:
ValueError: cannot reshape array of size 52428800 into shape
(640,640,3)
Thank you and have a good day,
Hesham
Edit 1:
That's the code:
import cv2
import scipy.io as sio
import numpy as np
matfile = 'docia.mat'
img = sio.loadmat(matfile)
img_reshaped = img['embedmap'].reshape(640, 640, 3)
cv2.imshow("segmented_map", img['embedmap'])
cv2.waitKey(0)`
Re-shaping is using when you want to retain all of the data but in a different shape. I believe that you are trying to drop 125 of the 128 channels. To do this you can just use indexing to get the first 3 channels:
img_reshaped = img['embedmap'][:, :, :3]
Also you are passing img['embedmap'], not the reshaped img_reshaped into cv2.imshow().
Although I would recommend looking at them 1 by 1 in grey scale.
for i in range(128):
cv2.imshow("segmented_map", img['embedmap'][:, :, i])
cv2.waitKey(0)

How to convert 1D array of pixels to image in python?

This is with respect to the FER2013 dataset. The data consists of 48x48 pixel grayscale images of faces. The CSV file contains three columns as (emotion, pixels, Usage), where Usage has any of three value - training, PrivateTest and PublicTest. I want to read the array of pixels, convert them into an image and save them in the respective folder named as per their Usage type.
I need python code that can do the above.
Following is my code
import pandas as pd
import numpy as np
from PIL import Image
df=pd.read_csv("fer2013.csv")
for rows in df:
arr=np.array(df['pixels'])
print(arr)
print(arr.shape)
img = Image.fromarray(arr.reshape(48,48), 'L')
img.save("dataset/df['Usage']/img.jpg", "JPEG")
The above code shows error:
cannot reshape array of size 35887 into shape (48,48).
In case there are any doubts (because I have been working with the FER dataset):
import pandas as pd
import numpy as np
from PIL import Image
df = pd.read_csv('fer2013.csv')
for image_pixels in df.iloc[1:,1]: #column 2 has the pixels. Row 1 is column name.
image_string = image_pixels.split(' ') #pixels are separated by spaces.
image_data = np.asarray(image_string, dtype=np.uint8).reshape(48,48)
img = Image.fromarray(image_data) #final image

Opening a single image

I'm trying to open an image with size (520,696) but when I use this
array = np.array([np.array(Image.open(folder_path+folders+'/'+'images'+'/'+image))], np.int32).shape`
I'm getting the shape as
(1, 520, 696, 4)
The problem is with this shape I can't convert it to image using toimage(array); I get
'arr' does not have a suitable array shape for any mode.
Any suggestions on how may I read that image using only (520,696)?
The problem is the additional dumb dimension. You can remove it using:
arr = np.squeeze(arr)
You should load the picture as a single picture instead of loading it as a stack and then removing the irrelevant stack dimension. The basic procedure could be something like this:
from PIL import Image
pic = Image.open("test.jpg")
pic.show() #yup, that's the picture
arr = np.array(pic) #convert it to a numpy array
print(arr.shape, arr.dtype) #dimension and data type
arr //= 2 #now manipulate this array
new_pic = Image.fromarray(arr) #and keep it for later
new_pic.save("newpic.bmp") #maybe in a different format

Conversion between Pillow Image object and numpy array changes dimension

I am using Pillow and numpy, but have a problem with conversion between Pillow Image object and numpy array.
when I execute following code, the result is weird.
im = Image.open(os.path.join(self.img_path, ifname))
print im.size
in_data = np.asarray(im, dtype=np.uint8)
print in_data.shape
result is
(1024, 768)
(768, 1024)
Why dimension is changed?
im maybe column-major while arrays in numpy are row-major
do in_data = in_data.T to transpose the python array
probably should check in_data with matplotlib's imshow to make sure the picture looks right.
But do you know that matplotlib comes with its own loading functions that gives you numpy arrays directly? See: http://matplotlib.org/users/image_tutorial.html
If your image is greyscale do:
in_data = in_data.T
but if you are working with rbg images you want to make sure your transpose operation is along only two axis:
in_data = np.transpose(in_data, (1,0,2))
actually this is because most image libraries give you images that are transpozed compared to numpy arrays. this is (i think) because you write image files line by line, so the first index (let's say x) refers to the line number (so x is the vertical axis) and the second index (y) refers to the subsequent pixel in line (so y is the horizontal axis), which is against our everyday coordinates sense.
If you want to handle it correctly you need to remember to write:
image = library.LoadImage(path)
array = (library.FromImageToNumpyArray(image)).T
and consequently:
image = library.FromNumpyArrayToImage(array.T)
library.WriteImage(image, path)
Which works also for 3D images. But i'm not promising this is the case for ALL image libraries - just these i worked with.

Categories

Resources