failing to read 16bit rgb images as numpy arrays in python - python

I am trying to load own image dataset from a folderwith two sub directories where all the images are 16bit png in RGB scale and the dimension of the images are (64*64). I am converting them to gray scale and forced the numpy array to have data type as uint16. It is returning me a list of images as (64*64) numpy arrays.
path="D:/PROJECT ___ CU/Images for 3D/imagedatanew/Training2/"
imageset=[]
image_labels=[]
for directory in os.listdir(path):
for file in os.listdir(path+directory):
print(path+directory+"/"+file)
img=Image.open(path+directory+"/"+file)
featurevector=numpy.array(img.convert("L"),dtype='uint16')
imageset.append(featurevector)
image_labels.append(directory)
But when I am trying to convert this list of 2D arrays into a 3D array, I cant do that.
im=numpy.array(imageset)
im.shape
>>> im.shape
>>> (207,) ##there are 207 images in total
I want the the array as (207,64,64)
and also when I run the im array, it returns me dtype as "object", which I cant understand

Related

Reading 3D numpy array

I have a dataset which comprises of the binary data of pixelated 50x50 images. The array shape is (50, 50, 90245). I want to reach 50x50 pixels of each of the 90245 images. How can I slice the array?
If data is the variable storing the image data, and i is the index of the image you want to access, then you can do:
data[:,:,i]
to get the desired image data.
If data is the variable storing the image data, and i is the index of the image you want to access, then you can do as #BrokenBenchmark suggested. In case you want a (50,50,1) 3D array as the output, you could do:
data[:,:,i:i+1]
to get the image as a 3D array.
Edit1: If you reshaped your data matrix to be of shape (90245,50,50), you can get the ith image by doing data[i,:,:] or just data[i] to get a (50,50) image. Similarly, to get a (1,50,50) image, you could do data[i:i+1,:,:] or just data[i:i+1].
Edit2: To reshape the array, you could use the swapaxes() function in numpy.

numpy.resize throws valueError despite image matrix product equaling the total image size

I am trying to resize a grayscale image into a numpy array like so:
return np.array(image.getdata()).reshape((im_height, im_width, 3)).astype(np.uint8)
and getting this error:
ValueError: cannot reshape array of size 1909760 into shape
(1024,1865,3)
I've read that the product of an images columns and rows (1024 x 1865) is supposed to equal the size of the array being reshaped - (1909760) which it does. I've also tried the same code on images with three channels and it works.
If you're using the PIL module for your image, you could try converting it to an RGB before getting the data. Something like this should work:
image = image.convert("RGB")
return np.array(image.getdata()).reshape((im_height, im_width, 3)).astype(np.uint8)
This works because when you convert from a grayscale to an RGB, PIL automatically sets each pixel to have three values, an R, G, and B.
Do not use .getdata(). That's pointless and a waste of effort. What'll happen is that a python list of integers is constructed as an intermediate. Directly converting to a numpy array is much more efficient.
Just use this:
# image = Image.open(...)
image_array = np.array(image)
Secondly you need to handle the conversion from grayscale to RGB, which you seem to want. Your PIL image appears to be grayscale, yet you want a numpy array with three channels (third dimension sized 3). You can either use PIL to convert, or you can use OpenCV.
PIL: image = image.convert("RGB") before converting to numpy (thanks Timmy Diehl, I don't use PIL that often)
OpenCV: image_array = cv.cvtColor(image_array, cv.COLOR_GRAY2BGR) after converting to numpy
Also note the order of color channels. PIL prefers RGB. OpenCV prefers BGR. What you need depends on what you'll do with the numpy array.

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:

How to convert 3D numpy array to nifti image in nibabel?

From this question How to convert Nifti file to Numpy array? , I created a 3D numpy array of nifti image. I made some modifications to this array, like I changed depth of the array by adding padding of zeroes. Now I want to convert this array back to nifti image, how can I do that?
I tried:
imga = Image.fromarray(img, 'RGB')
imga.save("modified/volume-20.nii")
but it doesn't identify nii extension. I also tried:
nib.save(img,'modified/volume-20.nii')
this is also not working, because img must be nibabel.nifti1.Nifti1Image if I want to use nib.save feature. In both of the examples above img is a 3D numpy array.
Assuming that you a numpy array and you want to use nib.save function, you need to first get the affine transformation.
Example:
# define the path to the data
func_filename = os.path.join(data_path, 'task-rest_bold.nii.gz')
# load the data
func = nib.load(func_filename)
# do computations that lead to a 3D numpy array called "output"
# bla bla bla
# output = np.array(....)
# to save this 3D (ndarry) numpy use this
ni_img = nib.Nifti1Image(output, func.affine)
nib.save(ni_img, 'output.nii.gz')
Now you will be able to overlay the output.nii.gz onto the task-rest_bold.nii.gz

Averaging multiple images in python

I'm trying to average 300 .tif images with this code :
import os, numpy, PIL
from PIL import Image
# Access all PNG files in directory
allfiles=os.listdir(os.getcwd())
imlist=[filename for filename in allfiles if filename[-4:] in[".tif",".TIF"]]
# Assuming all images are the same size, get dimensions of first image
w,h = Image.open(imlist[0]).size
N = len(imlist)
# Create a numpy array of floats to store the average (assume RGB images)
arr = numpy.zeros((h,w,3),numpy.float)
# Build up average pixel intensities, casting each image as an array of floats
for im in imlist:
imarr = numpy.array(Image.open(im),dtype=numpy.float)
arr = arr+imarr/N
# Round values in array and cast as 16-bit integer
arr = numpy.array(numpy.round(arr),dtype=numpy.uint16)
# Generate, save and preview final image
out = Image.fromarray(arr,mode="RGB")
out.save("Average.tif")
And it gives me a TypeError like that :
imarr = numpy.array(Image.open(im),dtype=numpy.float)
TypeError: float() argument must be a string or a number, not 'TiffImageFile'
I understand that it doesn't really like to put a TIF image in the numpy array (it also doesn't work with PNG images). What should I do ? Splitting each image into R, G and B arrays to average and then merge everything seems too memory consuming.
It should work as is, checked right now with PIL (pillow 2.9.0) and numpy 1.9.2.

Categories

Resources