simple-itk: reading a sequence from a single tiff file - python

I've got a tif file which contains a series of images. It is a 3D volume of pixels, produced by a CT-scan.
But after reading the image with simple-itk, there is only a single layer:
reader = sitk.ImageFileReader()
reader.SetFileName("FILENAME.tif")
img = reader.Execute()
img.GetDepth() # 0
arr = sitk.GetArrayFromImage(img)
arr.shape # (512, 512, 4)
How can I configure simple-itk to read the whole sequence of images from the tif file ?
Reading the docs for simple-itk shows how to read sequences of images, from sequences of files. That's not what I need, there is a single tif file for the 3D data.
I am able to read this with the tifffile module, it is able to see the correct number of slices and the plots look good, too. So the data itself seems to be valid.
I'm afraid since this is medical data, it's not possible for me to provide a sample. I'm just interested in the corresponding simple-itk documentation.

Likely the Tiff tags are not fully supported by ITK's ImageIO. Providing a sample data file would be best to determine the structure of the tiff file. Without that some information can be obtained with the command line tool tiffinfo from the libtiff tools to share to reveal the structure of the file.

Related

How to find the original format of images (pages) present in a tiff file using python?

I have a multi-page tiff file (merged.tiff) out of which I need to extract individual images in their original format. PIL allows you to iterate through pages and writing them to disk in a format I need (png/jpg).
Ex:
from PIL import Image
img = Image.open('merged.tiff')
for i in range(img.n_frames):
try:
img.seek(i)
img.save(f'individual_{i}.jpg')
img.save(f'individual_{i}.png')
except EOFError:
break
But is there a way to know the original format of those images?
I have tried with tifffile and tiffany which allow me to convert the pages to a numpy array and then write to disk as an image, but they don't allow me to know the source format of the images contained in the TIFF file.
In the most general case, I believe this is impossible, because it is perfectly feasible to take, say, a JPEG image and include it in the TIFF file as an uncompressed RGB array.
Realistically, though, you should be able to look at some of the tags of the TIFF file, e.g. Compression, to make an educated guess about what the image used to be. Tools like tiffinfo and tiffdump (from the libtiff package) can be used to examine the TIFF file.

How to save float64 image data without loss of information, while being able to visualize it

I'm trying to implement frequency spectrum image watermarking, using the Fast Fourier Transform and everything is working perfectly, except the fact that I can't save the resulting watermarked image without running into trouble. Since the application is meant to be user-friendly, no hacks regarding photo viewing are acceptable. The user has to be able to download the resulting file and view it as is, without any further modifications.
The code basically goes like this:
import cv, imageio
image = cv2.imread(imagePath, cv2.IMREAD_UNCHANGED)
watermark = cv2.imread(wmPath, cv2.IMREAD_UNCHANGED)
# result is float64, due to the transition from the frequency spectrum to spatial
result = embed_watermark(image, watermark)
imageio.imwrite('result.tiff', result)
result2 = imageio.imread('result.tiff') # Still float64, thanks to tiff format
detection = detect_watermark(result, image)
So, the code is working as wanted, it prevents data loss, thanks to the tiff container, which allows for floating-point pixel values. However, the saved file ('result.tiff') can't be opened with any photo viewer included in MS Windows. If I use any other of the usual containers (jpeg, png, bmp), I am able to visualise the resulting image, but end up losing the watermark information.
I've tried solutions discussed here and here and read the documentation, but I don't seem to wrap my head around this. I have also tried opening the image using FIJI (following Ander Biguri's suggestion, but I get this error: "ImageJ can only open 8 and 16 bit/channel images (64)"
How could I possibly save the file without losing the watermark data, nor the ability to open the resulting file for visualisation?

How to compare two image files pixel by pixel in python using selenium?

I want to compare two images (.png format) pixel by pixel using selenium in python. Or how could i do it using pillow library.
I have a base image and i get the compare image by taking screenshot of the webpage. I want to compare those two images and assert that they are equal. how can I do it.
Below is what I have tried:
def assert_images_are_equal(base_image, compare_image):
with open(base_image, 'rb') as f1, open(compare_image, 'rb') as f2:
base_image_contents = f1.read()
compare_image_contents = f2.read()
assert base_image_contents == compare_image_contents
But this doesnt work always. I want to compare pixel by pixel. Could someone help me with this using pillow library or any other library apart from PIL? thanks.
It is rather difficult to say whether 2 images are the same or similar, because it depends on your definitions of "same" and "similar".
You can make a solid red image, save it as a PNG and then save the exact same image again and it could be different because the PNG format contains a timestamp in the image header that may have ticked over to the next second in between saves.
You can make a solid red PNG file that is 8-bits deep, and another that is 16-bits deep and you cannot see the difference but the data will be grossly different.
You can make a TIF file in Motorola byte order and the same file in Intel byte order. Visually, and in calculations, they will be indistinguishable, but the files will be grossly different.
You can make a GIF file that is red and it will look no different from a PNG file but the files will differ.
You can make a palette image and a true-colour image and the pixels will be grossly different but they will look identical.
You could make a simple black image with a white rectangle in the middle and write it using one JPEG library and it will come out different from the same image written with a different JPEG library, or even a different release version of the same library.
There are many more cases...
One a more helpful note, you may want to look at Perceptual Hashing which tells you if images look pretty similar. One library that does Perceptual Hashing is ImageMagick and it has a Python binding here and here.

How to get number of images in NIfTi object? (nibabel)

I have a Nifti object generated from a directory of dicom files.
It seems that the Nifti should know how many frames it holds, but all I can find in the header info is the shape. The problem is, the shape is at times (num_images, x, y) and at times (x, y, num_images).
The only nibabel functions I found relevant where from the Ecat library. I am not familiar with ecat format, but I want my method to work for any nii file. I am working with the nibabel library.
Is there a way to retrieve the number of images in a Nifti file?
I'm guessing you're looking at fMRI, DTI or ASL data.
Say your 4D nii stack is called 'data.nii.'
Just go into that directory and do:
mri = nib.load('data.nii')
mri.shape
The fourth element you see will be the number of volumes. You can access it thusly: mri.shape[3] if you need it for some kind of purpose in your programs.
This works consistently for me. If your data are "stacked" in an inconsistent orientation, you are going to have to get fancy.
You could include checks based off of the dimensionality of your images. For example if you know that your images are 128x128x128, then you can go ahead and get whichever element of mri.shape isn't 128, but this approach is suboptimal for a few reasons.

How to save jpeg data that is identical to the original jpeg file using OpenCV

I'm using OpenCV and Python. I have loaded a jpeg image into a numpy array. Now i want to save it back into jpeg format, but since the image was not modified, I don't want to compress it again. Is it possible to create a jpeg from the numpy array that is identical with the jpeg that it was loaded from?
I know this workflow (decode-encode without doing anything) sounds a bit stupid, but keeping the original jpeg data is not an option. I'm interested if it is possible to recreate the original jpeg just using the data at hand.
The question is different from Reading a .JPG Image and Saving it without file size change, as I don't modify anything in the picture. I really want to restore the original jpeg file based on the data at hand. I assume one could bypass the compression steps (the compression artifacts are already in the data) and just write the file in jpeg format. The question is, if this is possible with OpenCV.
Clarified answer, following comment below:
What you say makes no sense at all; You say that you have the raw, unmodified, RGB data. No you don't. You have the uncompressed data that has been reconstructed from the compressed jpeg file.
The JPEG standards specify how to un-compress an image / video. There is nothing in the standard about how to actually do this compression, so your original image data could have been compressed any one of a zillion different ways. You have no way of knowing the decoding steps that were required to recreate your data, so you cannot reverse them.
Image this.
"I have a number, 44, please tell me how I can get the original
numbers that this came from"
This is, essentially, what you are asking.
The only way you can do what you want (other than just copy the original file) is to read the image into an array before loading into openCV. Then if you want to save it, then just write the raw array to a file, something like this:
fi = 'C:\\Path\\to\\Image.jpg'
fo = 'C:\\Path\\to\\Copy_Image.jpg'
with open(fi,'rb') as myfile:
im_array = np.array(myfile.read())
# Do stuff here
image = cv2.imdecode(im_array)
# Do more stuff here
with open(fo,'wb') as myfile:
myfile.write(im_array)
Of course, it means you will have the data stored twice, effectively, in memory, but this seems to me to be your only option.
Sometimes, no matter how hard you want to do something, you have to accept that it just cannot be done.

Categories

Resources