fepegar / torchio Goto Github PK
View Code? Open in Web Editor NEWMedical imaging toolkit for deep learning
Home Page: http://www.torchio.org
License: Apache License 2.0
Medical imaging toolkit for deep learning
Home Page: http://www.torchio.org
License: Apache License 2.0
For some Transform : histogram_standardization rescale z_normalization there may be an interest to use a mask (just to compute percentyl or min max values) then the transform is apply to the all images
This is possible with histogram_standardization (and we should add the option with rescale)
My point is that a masking_function is not an easy job, and I do prefer to use mask compute independently (with your prefered software)
In the case of external mask, you can easily use them by including then in the ImageDataset
suj = [[
Image('T1','/oneT1.nii.gz',INTENSITY),
Image('mask','/coresponding_mask.nii.gz',LABEL)
]]
Then you can use a parameter mask_field_name to get this mask when needed
here is an example of such an implementation
https://github.com/romainVala/torchio/blob/master/torchio/transforms/rescale_within_mask.py
but I thing it is better, to directly incorporate it as an optional feature of the Rescale class with something like
if sefl.mask_field_name is not None :
mask_data = sample[self.mask_field_name]['data']
About ZNormalization I would prefer to set use_mean_threshold to False by default and add the possiblity to use either a masking_function or the external mask
For histogram_standardization, a masking_function is expected, (but not use in the call), I added the possibility of external mask
https://github.com/romainVala/torchio/blob/master/torchio/transforms/histogram_standardization.py
of course those option are exclusive, and the user should set only one of them, I am not sure what the best way to code it properly, I did something like
if masking_function is not None:
mask = masking_function(img)
else:
if mask_data is not None:
mask = mask_data
else:
mask = np.ones_like(img, dtype=np.bool)
Hello
I get the following error when I try to apply the bias_field
/data/romain/toolbox_python/torchio/torchio/transforms/random_bias_field.py in apply_transform(self, sample)
34 bias_field = self.generate_bias_field_map(
35 image_dict['data'], self.order, coefficients)
---> 36 image_dict['data'] *= torch.from_numpy(bias_field)
37 return sample
38
RuntimeError: unsupported operation: more than one element of the written-to tensor refers to a single memory location. Please clone() the tensor before performing the operation.
if I change the corresponding line with
iii = image_dict['data'] * torch.from_numpy(bias_field)
image_dict['data'] = iii
it pass,
very strange I do not understand why ...
This is useful when images in the dataset have different sizes.
See TensorFlow and PyTorch implementations.
Related to #30
$ torchio-transform /tmp/t1_ras.nii ToCanonical /tmp/t1_ras.nii
[1] 2066 bus error (core dumped) torchio-transform /tmp/t1_ras.nii ToCanonical /tmp/t1_ras.nii
And /tmp/t1_ras.nii
gets corrupted.
This is an issue with NiBabel: nipy/nibabel#492
I get an error with
transfo = Compose(( Rescale(masking_method='mask', verbose=True),))
In the init of NormalizationTransform you use self.masking_method
but it is not assign
I may be a good feature to add, if we can compose augmentation in a similar way as
https://albumentations.readthedocs.io/en/latest/probabilities.html#oneof-block
this make it very modular
I notice that you set (in _write_nifti in io.py)
nii.header['sform_code'] = 0
It is more robust (for other software) to set both sform and qform. I would prefer to have
nii.header['sform_code'] = 1
this will save both sfrom and qform (to the same value)
Related to #24
Related to #22
When using the save_sample method from ImagesDataset
the nifti have a wrong dimention one should change
tensor = sample[key]['data']
by
tensor = sample[key]['data'].squeeze()
Not sure if this is the rigth place for this function, why not put it directly in io.py ?
To reproduce:
from torchio import Image, ImagesDataset, INTENSITY
from torchio.transforms import (
RandomAffine,
RandomFlip,
RandomNoise,
RandomBiasField,
RandomElasticDeformation,
RandomMotion,
ZNormalization,
)
paths_list = [[
Image('image', '~/Dropbox/MRI/t1.nii.gz', INTENSITY),
]]
seed = None
verbose = True
transforms = [
ZNormalization(verbose=verbose),
RandomMotion(proportion_to_augment=1, seed=seed, verbose=verbose),
# RandomNoise(seed=seed, verbose=verbose),
# RandomBiasField(seed=seed, verbose=verbose),
# RandomFlip(axes=(0,), seed=seed, verbose=verbose),
# RandomAffine(seed=seed, verbose=verbose),
# RandomElasticDeformation(proportion_to_augment=0.1, seed=seed, verbose=verbose),
]
dataset = ImagesDataset(paths_list)
sample = dataset[0]
for i, transform in enumerate(transforms):
transformed = transform(sample)
name = transform.__class__.__name__
path = f'/tmp/{i}_{name}.nii.gz'
dataset.save_sample(transformed, dict(image=path))
@romainVala do you know why this could be? I'm probably missing some theory about the Fourier transform.
Hi fernando,
I recently switched from tf to pytorch and I was really happy to find your library.
Great work! Thanks.
I added a more efficient image sampler to sample random patches which should contain
at least one point of a specific label.
https://github.com/lab-midas/midas-torchio/blob/dev_tobias/torchio/data/sampler/label.py
(code and examples are still a bit messy, I will work on this the next days).
But maybe you can use (parts of) it ;)
There was also a minor issue if the patch size is equal to the image size in a dimension
(missing +1, rand numbers low=a high=b -> sample from [a,b) so b can be the max_size). I corrected this.
This is very helpful to use the patch sampler as a slice sampler (for instance slicing 512x512 from 512x512x156 volumes).
Cheers
Tobias
It can be useful to pad the images in the transform operations.
In particular, the current grid sampler ignore the borders of the full image, adding a padding of the size of the border could solve this problem (if consistent with training).
This happens sometimes. I need to figure out how to reproduce this error.
Exception thrown in SimpleITK Euler3DTransform_SetMatrix: /tmp/SimpleITK-build/ITK-prefix/include/ITK-4.13/itkRigid3DTransform.hxx:94:
itk::ERROR: Euler3DTransform(0x558bdd7a4780): Attempting to set a non-orthogonal rotation matrix
Hi there
Just a small issue in order to fully understand the input format logic
I see in torchio.py that you define 3 data type : Intensity, label and sampling_map
what is the implication of choosing one of those ?
Why in your example_multimodal.py do you define one_subject_dict with a 'label' which has type=torchio.INTENSITY ? (why not torchio.LABEL ?)
many thanks
Reported in #50.
@romainVala reported this in #24
Use case: loading an MRI and CT from the same patients. We probably want very different transforms for each image, but we still want them to happen in the same parallel process.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.