convert greyscale image back to vector - python

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

Related

How do I create image from binary data BSQ?

I've got a problem. I'm trying create image from binary data which I got from hyperspectral camera. The file which I have is in BSQ uint16 format. From the documentation I found out that images contained in the file (.dat) have a resolution of 1024x1024 and there are 24 images in total. The whole thing is to form a kind of "cube" which I want use in the future to creat multi-layered orthomosaic.
I would also like to add that I am completely new in python but I try to be up to date with everything I need. I hope that everything what I have written is clear and uderstandable.
At first I tried to use Numpy liblary to creating 3D array but ended up with an arrangement of random pixels.
from PIL import Image
import numpy as np
file=open('Sequence 1_000021.dat','rb')
myarray=np.fromfile(file,dtype=np.uint16)
print('Size of new array',":", len(myarray))
con_array=np.reshape(myarray,(24,1024,1024),'C')
naPIL=Image.fromarray(con_array[1,:,:])
naPIL.save('naPIL.tiff')
The result: enter image description here
Example of image which I want to achieve (thumbnail): enter image description here
As suspected it's just byte order, I get a sensible looking image when running the following code in a Jupyter notebook:
import numpy as np
from PIL import Image
# open as big-endian, convert to native order, then reshape as appropriate
raw = np.fromfile(
'./Sequence 1_000021.dat', dtype='>u2'
).astype('uint16').reshape((24, 1024, 1024))
# display inline
Image.fromarray(raw[1,:,:])

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)

convert .nii to .tif using imwrite, it saves black image insted of the image

I want to convert .nii images to .tif to train my model using U-Net.
1-I looped through all images in the folder.
2-I looped through all slices within each image.
3-I saved each slice as .tif.
The training images are converted successfully. However, the labels (masks) are all saved as black images. I want to successfully convert those masks from .nii to .tif, but I don't know how. I read that it could be something with brightness, but I didn't get the idea clearly, so I couldn't solve the problem until now.
The only reason for this conversion is to be able to train my model. Feel free to suggest a better idea, if anyone can share a way to feed the network with the .nii format directly.
import nibabel as nib
import matplotlib.pyplot as plt
import imageio
import numpy as np
import glob
import os
import nibabel as nib
import numpy as np
from tifffile import imsave
import tifffile as tiff
for filepath in glob.iglob('data/Task04_Hippocampus/labelsTr/*.nii.gz'):
a = nib.load(filepath).get_fdata()
a = a.astype('int8')
base = Path(filepath).stem
base = re.sub('.nii', '', base)
x,y,z = a.shape
for i in range(0,z):
newimage = a[:, :, i]
imageio.imwrite('data/Task04_Hippocampus/masks/'+base+'_'+str(i)+'.tif', newimage)
Unless you absolutely have to use TIFF, I would strongly suggest using the NiFTI format for a number of important reasons:
Image values are often not arbitrary. For example, in CT images the values correspond to x-ray attenuation (check out this Wikipedia page). TIFF, which is likely to scale the values in some way, is not suitable for this.
NIfTI also contains a header which has crucial geometric information needed to correctly interpret the image, such as the resolution, slice thickness, and direction.
You can directly extract a numpy.ndarray from NIfTI images using SimpleITK. Here is a code snippet:
import SimpleITK as sitk
import numpy as np
img = sitk.ReadImage("your_image.nii")
arr = sitk.GetArrayFromImage(img)
slice_0 = arr[0,:,:] # this is a 2D axial slice as a np.ndarray
As an aside: the reason the images where you stored your masks look black is because in NIfTI format labels have a value of 1 (and background is 0). If you directly convert to TIFF, a value of 1 is very close to black when interpreted as an RGB value - another reason to avoid TIFF!

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.

Loading a Nifti through Nibabel and using the shape function

I have a nifti file 1.nii.gz
Now, i never dealt with nifti files.
So, just opening it using this software i realized that a nii.gz is a sort of container that contains 3 arrays of 2d pictures. In fact, if i scroll the mouse i can see 448 2d picture for the "direction" labeled in the picture as 1, 448 2d pictures for the "direction" 2 and 25 2d pictures for the "direction" 3.
After this, i opened the shell and i tried to use this nii.gz with Nibabel library
import nibabel as nib
img = nib.load(1.nii.gz)
But, if i type
img.shape
i get (448,448,25) as result, so it seems that this .nii.gz is a 3d matrix and not a container with 3 arrays of 2d pictures. Can you explain me ?
Nifti is a medical images format, to store both images, and companied data, the images are usually in grayscale, and they are taken as slices, each slice with a different cross-section of the body.
They store all the slices in the same array, and sometimes they take the slices during different times so sometimes they add a fourth dimension to the array.
So to show the images, or manipulate them, you can slice them and see the images inside.
In your case the shape of your data (448,448,25) tells that:
There are 25 images (slices) with dimensions 448 x 448
import nibabel as nib
import matplotlib.pyplot as plt
# Change the path to your path
path = 'path to img.nii.gz'
Nifti_img = nib.load(path)
nii_data = my_img.get_fdata()
nii_aff = my_img.affine
nii_hdr = my_img.header
print(nii_aff ,'\n',nii_hdr)
print(nii_data.shape)
if(len(nii_data.shape)==3):
for slice_Number in range(nii_data.shape[2]):
plt.imshow(nii_data[:,:,slice_Number ])
plt.show()
if(len(nii_data.shape)==4):
for frame in range(nii_data.shape[3]):
for slice_Number in range(nii_data.shape[2]):
plt.imshow(nii_data[:,:,slice_Number,frame])
plt.show()

Categories