python tifffile.imsave to save 3 images as 16bit image stack - python

I'm trying to save a numpy array as 16bit image stack using tifffile.imsave. This works perfectly fine for 1,2, or >= 5 images. However, if I try to save 3 or 4 images in one stack, image readers (such as ImageJ) interpret the images as rgb-channels, or as rgb-channels plus one gray value channel, respectively. Is there a way to avoid this e.g. by adding the right flags or tags?
import numpy as np
from tifffile import imsave
data = np.random.rand(3, 301, 219).astype(np.uint16)
imsave('myFileName.tif', data)

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,:,:])

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

How can I visualize a large file read in numpy memmap format?

I am trying to read czi format images, But because they need a lot of memmory I tried reading them in memmap file.
Here is the code I used>
import czifile as czi
fileName = "Zimt3.czi"
# read file to binary
file = czi.CziFile(fileName)
imageArr = file.asarray(out="/media/my drive/Temp/temp.bin")
Now imageArr is a variable with dimensons of (9,3,29584,68084,1) in memmap. These are high resolution microscopic images from Carl Zeiss device.
Here is an screenshot of more specifications.
I think this means that imageArr contains 9 images with the dimention of (29584,68084,3)
But I cant extract this kind of numpy array to visualize as an image.
Can you please help me convert (9,3,29584,68084,1) in memmap to (29584,68084,3) images please.
It looks like a very large file. If you just want to visualize it, you can use slideio python package (http://slideio.com). It makes use of internal image pyramids. You can read the image partially with high resolution or the whole image with low resolution. The code below rescales the image so that the width of the delivered raster will be 500 pixels (the height is computed to keep the image size ratio).
import slideio
import matplotlib.pyplot as plt
slide = slideio.open_slidei(file_path="Zimt3.czi",driver_id="CZI")
scene = slide.get_scene(0)
block = scene.read_block(size=(500,0))
plt.imshow(scene.read_block())
Be aware that matplotlib can display images if they have 1 or 3 channels. A CZI file can have an arbitrary number of channels. In this case you have to select what channels you want to display:
block = scene.read_block(size=(500,0), channel_indices=[0,2,5])
Another problem with visualization can be if your file is a 3 or 4D image. In this case, slideio returns 3d or 4d numpy array. Matplotlib cannot display 3d or 4d images. You will need to look for a specific visualization package or select a z-slice and/or time-frame:
block = scene.read_block(size=(500,0), channel_indices=[0,2,5], slices=(0,1), frames=(1,2))
For more details see the package documentation.

Categories