Skull stripping with python/simpleITK - python

I'm trying to perform a skull stripping with simpleITK in python.
I'm using the StripTsImageFilter function as follows:
#upload data
# Path of nii img
path = r'C:\Users\Kate\Jupyter\DataThesis\PROGRESSION\0003\fet.nii.gz'
# Read the .nii image with SimpleITK:
img = sitk.ReadImage(path)
#read atlas and atlasmap
#Obtained from 3DSlicer documentation: https://www.slicer.org/wiki/Documentation/Nightly/Modules/SwissSkullStripper
atlas = sitk.ReadImage(r'C:\Users\Kate\Jupyter\thesis\atlasImage.mha')
atlasMask = sitk.ReadImage(r'C:\Users\Kate\Jupyter\thesis\atlasMask.mha')
#Skull stripping
#https://www.istb.unibe.ch/e43946/e43949/e158631/e187931/pane187932/e187939/files187941/article_eng.pdf
brainMask = sitk.StripTsImageFilter(img, atlas, atlasMask)
I get the error 'AttributeError: module 'SimpleITK' has no attribute 'StripTsImageFilter''
I have tried implementing img.StripTsImageFilter and tried using sitk.SkullStrip.StripTsFilter as well.
Does anyone know how to solve this?

StripTsImageFilter is a 'remote' module for ITK. So it is not wrapped by SimpleITK and is not even built by default in ITK.
To gain access to it in Python you're going to have to use ITK's Python wrapping, and you're going to have to build ITK-Python yourself, since it is not in the pre-build ITK-Python on PyPi.

As Dave pointed out, the StripTsImageFilter is included in SimpleITK (or 'raw' ITK) by default. You can install the remote module from PyPi like so:
pip install itk-skullstripping
More information is available here:
https://github.com/InsightSoftwareConsortium/ITKSkullStrip
Converting itk to sitk and back is explained here: https://discourse.itk.org/t/in-python-how-to-convert-between-simpleitk-and-itk-images/1922

Related

Python exifread - Parsing difficulties

I'm trying to get the coordinates of a number of photos, i.e. I'm trying to get the exif data using a python script. The goal is to georeference all the photos and display their locations on a map. I am encountering problems with exif, however. I'm on Windows (64bit) and installed the corresponding (Strawberry) Perl software and then the Exiftool module (version 12.30) using Anaconda (Navigator), but to no avail. It gives me the following error: ModuleNotFoundError: No module named 'exif'. If I use the command pip install exif it tells me that the requirements are already met. What am I missing here? I'll gladly provide more information if required.
... I also tried an alternative: the module exifread works without import problems but does not seem to have all the necessary functionality (I can read the coordinates, but can't handle the extraction of the coordinates, it gives me a IfdTag-object when I would like an array of the degrees, minutes and seconds that I can then further process.)
There is a utility function exifread.utils.get_gps_coord() that provides convenient method to access coordinates as tuple in the format (latitude, longitude). Note negative value for latitude means South, negative value for longitude - West
example
import exifread
path = 'image.jpg'
with open(path, 'rb') as f:
tags = exifread.process_file(f, details=False)
coord = exifread.utils.get_gps_coords(tags)
print(coord)
For sake of completeness, there are also other modules to work with exif:
Pillow - there is functionality to work with exif
piexif
Also, as mentioned in the comments - you can use ExifTool (Perl software), via subprocess

Is there any problem with the OpenSlide.read_region function?

I am using the python API of openslide packages to read some ndpi file.When I use the read_region function, sometimes it return a odd image. What problems could have happend?
I have tried to read the full image, and it will be worked well. Therefore, I think there is no problem with the original file.
from openslide import OpenSlide
import cv2
import numpy as np
slide = OpenSlide('/Users/xiaoying/django/ndpi-rest-api/slide/read/21814102D-PAS - 2018-05-28 17.18.24.ndpi')
image = slide.read_region((1, 0),6, (780, 960))
image.save('image1.png')
The output is strange output
As the read_region documentation says, the x and y parameters are always in the coordinate space of level 0. For the behavior you want, you'll need to multiply those parameters by the downsample of the level you're reading.
This appears to be a version-realted bug, see also
https://github.com/openslide/openslide/issues/291#issuecomment-722935212
The problem seems to relate to libpixman verions 0.38.x . There is a Workaround section written by GunnarFarneback suggesting to load a different version first e.g.
export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libpixman-1.so.0.34.0
upadte easier solution is:
We are using Python 3.6.8+ and this did the trick for us: conda install pixman=0.36.0

How to load *.hdr files using python

I would like to read an environment map in *.hdr file format. It seems that very popular libraries doesn't support .hdr file reading, for example, OpenCV, PIL etc.. So how to read a .hdr file into a numpy array?
I found ImageIO very useful. It can handle many image file formats including .hdr images. Here is the list: ImageIO Formats
It can be easily installed using easy_install or pip.
For some reason when I was trying to load a MRI image in .hdr format using format='HDR-FI' it was returning Could not load bitmap <path to image>: : RGBE read error
But if you type imageio.show_formats() it returns a list of formats including "ITK - Insight Segmentation and Registration Toolkit", where it shows that it can handle .hdr images as well.
So my alternative was to use:
pip install itk
hdr_path = "<path to image>"
img = imageio.imread(hdr_path, 'ITK') # returns a tuple
img = np.array(img) # transforms to numpy array

Python get mac clipboard contents

How can I, using Python (2.7) get the contents of the Mac clipboard. Is there a better way than making a wrapper around pbpaste?
Thanks!
PyObjC is the way to go:
#!/usr/bin/python
from AppKit import NSPasteboard, NSStringPboardType
pb = NSPasteboard.generalPasteboard()
pbstring = pb.stringForType_(NSStringPboardType)
print u"Pastboard string: %s".encode("utf-8") % repr(pbstring)
This only supports text and will return None otherwise. You can extend it to support other data types as well, see NSPastboard Class Reference.
Have you looked at the xerox module?
It is supposed to support windows, OS X and Linux
Usage is as follows:
xerox.copy(u'some string')
And to paste:
>>> xerox.paste()
u'some string'
If you have installed pandas, you can use the function in pandas as follows:
from pandas.io.clipboard import clipboard_get
text = clipboard_get()
The problem with the xerox module and most code samples I've found for "get the contents of the Mac clipboard" is that they return plain text only. They don't support hyperlinks, styles, and such, so they're not really able to access the full contents provided by apps like Microsoft Word and Google Chrome.
Standing on the shoulders of others, I finally figured out how to do this. The resulting richxerox module is available on PyPI and Bitbucket.
Though this question is old, I'm leaving breadcrumbs here because I consistently re-found this page via Google while searching for the answer.
Do you know PyObjC? I guess you could use it to write a Py wrapper which interfaces with NSPasteboard. This might be more "elegant" than shelling out to pbpaste.
You can grab the clipboard (and the screen) with PIL/Pillow on a Mac like this:
from PIL import ImageGrab, Image
# Grab clipboard and save to disk
clip = ImageGrab.grabclipboard()
clip.save("clip.png")
Just for completeness, you can grab the screen like this:
screen = ImageGrab.grab()
# That results in this:
# <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=5120x2880 at 0x110BB7748>
# Save to disk
screen.save("screen.png")

How to check if a file is a valid image file?

I am currently using PIL.
from PIL import Image
try:
im=Image.open(filename)
# do stuff
except IOError:
# filename not an image file
However, while this sufficiently covers most cases, some image files like, xcf, svg and psd are not being detected. Psd files throws an OverflowError exception.
Is there someway I could include them as well?
I have just found the builtin imghdr module. From python documentation:
The imghdr module determines the type
of image contained in a file or byte
stream.
This is how it works:
>>> import imghdr
>>> imghdr.what('/tmp/bass')
'gif'
Using a module is much better than reimplementing similar functionality
UPDATE: imghdr is deprecated as of python 3.11
In addition to what Brian is suggesting you could use PIL's verify method to check if the file is broken.
im.verify()
Attempts to determine if the file is
broken, without actually decoding the
image data. If this method finds any
problems, it raises suitable
exceptions. This method only works on
a newly opened image; if the image has
already been loaded, the result is
undefined. Also, if you need to load
the image after using this method, you
must reopen the image file. Attributes
Additionally to the PIL image check you can also add file name extension check like this:
filename.lower().endswith(('.png', '.jpg', '.jpeg', '.tiff', '.bmp', '.gif'))
Note that this only checks if the file name has a valid image extension, it does not actually open the image to see if it's a valid image, that's why you need to use additionally PIL or one of the libraries suggested in the other answers.
A lot of times the first couple chars will be a magic number for various file formats. You could check for this in addition to your exception checking above.
One option is to use the filetype package.
Installation
python -m pip install filetype
Advantages
Fast: Does its work by loading only the first few bytes of your image (check on the magic number)
Supports different mime type: Images, Videos, Fonts, Audio, Archives.
Example
filetype >= 1.0.7
import filetype
filename = "/path/to/file.jpg"
if filetype.is_image(filename):
print(f"{filename} is a valid image...")
elif filetype.is_video(filename):
print(f"{filename} is a valid video...")
filetype <= 1.0.6
import filetype
filename = "/path/to/file.jpg"
if filetype.image(filename):
print(f"{filename} is a valid image...")
elif filetype.video(filename):
print(f"{filename} is a valid video...")
Additional information on the official repo: https://github.com/h2non/filetype.py
Update
I also implemented the following solution in my Python script here on GitHub.
I also verified that damaged files (jpg) frequently are not 'broken' images i.e, a damaged picture file sometimes remains a legit picture file, the original image is lost or altered but you are still able to load it with no errors. But, file truncation cause always errors.
End Update
You can use Python Pillow(PIL) module, with most image formats, to check if a file is a valid and intact image file.
In the case you aim at detecting also broken images, #Nadia Alramli correctly suggests the im.verify() method, but this does not detect all the possible image defects, e.g., im.verify does not detect truncated images (that most viewers often load with a greyed area).
Pillow is able to detect these type of defects too, but you have to apply image manipulation or image decode/recode in or to trigger the check. Finally I suggest to use this code:
from PIL import Image
try:
im = Image.load(filename)
im.verify() #I perform also verify, don't know if he sees other types o defects
im.close() #reload is necessary in my case
im = Image.load(filename)
im.transpose(Image.FLIP_LEFT_RIGHT)
im.close()
except:
#manage excetions here
In case of image defects this code will raise an exception.
Please consider that im.verify is about 100 times faster than performing the image manipulation (and I think that flip is one of the cheaper transformations).
With this code you are going to verify a set of images at about 10 MBytes/sec with standard Pillow or 40 MBytes/sec with Pillow-SIMD module (modern 2.5Ghz x86_64 CPU).
For the other formats xcf,.. you can use Imagemagick wrapper Wand, the code is as follows:
Check the Wand documentation: here, to installation: here
im = wand.image.Image(filename=filename)
temp = im.flip;
im.close()
But, from my experiments Wand does not detect truncated images, I think it loads lacking parts as greyed area without prompting.
I red that Imagemagick has an external command identify that could make the job, but I have not found a way to invoke that function programmatically and I have not tested this route.
I suggest to always perform a preliminary check, check the filesize to not be zero (or very small), is a very cheap idea:
import os
statfile = os.stat(filename)
filesize = statfile.st_size
if filesize == 0:
#manage here the 'faulty image' case
On Linux, you could use python-magic which uses libmagic to identify file formats.
AFAIK, libmagic looks into the file and tries to tell you more about it than just the format, like bitmap dimensions, format version etc.. So you might see this as a superficial test for "validity".
For other definitions of "valid" you might have to write your own tests.
You could use the Python bindings to libmagic, python-magic and then check the mime types. This won't tell you if the files are corrupted or intact but it should be able to determine what type of image it is.
Adapting from Fabiano and Tiago's answer.
from PIL import Image
def check_img(filename):
try:
im = Image.open(filename)
im.verify()
im.close()
im = Image.open(filename)
im.transpose(Image.FLIP_LEFT_RIGHT)
im.close()
return True
except:
print(filename,'corrupted')
return False
if not check_img('/dir/image'):
print('do something')
Extension of the image can be used to check image file as follows.
import os
for f in os.listdir(folderPath):
if (".jpg" in f) or (".bmp" in f):
filePath = os.path.join(folderPath, f)
format = [".jpg",".png",".jpeg"]
for (path,dirs,files) in os.walk(path):
for file in files:
if file.endswith(tuple(format)):
print(path)
print ("Valid",file)
else:
print(path)
print("InValid",file)

Categories

Resources