fepegar / torchio

Medical imaging toolkit for deep learning
http://www.torchio.org
Apache License 2.0
2.04k stars 239 forks source link

Preferred order of augmentations/best practices in documentation #820

Open LvanderGoten opened 2 years ago

LvanderGoten commented 2 years ago

Thank you very much for your great project, it literally saved me countless hours of work!

I wonder whether it would be possible in the documentation to hint how augmentations should generally be ordered ("best practices").

I have the following pipeline and I am quite unsure whether the ordering makes sense, also some augmentations cannot work with np.uint8 while others can.

transform = torchio.Compose([
    torchio.RandomMotion(p=augmentation_probs['random_motion']),
    torchio.RandomSpike(p=augmentation_probs['random_spike']),
    torchio.RandomBlur(p=augmentation_probs['random_blur']),
    torchio.RandomBiasField(p=augmentation_probs['random_bias_field']),
    torchio.RandomGhosting(p=augmentation_probs['random_ghosting']),
    torchio.ZNormalization(),
    torchio.RandomNoise(p=augmentation_probs['random_noise']),
    torchio.RandomFlip(p=augmentation_probs['random_flip']),
    torchio.OneOf({
        torchio.RandomAffine(): augmentation_probs['random_affine'],
        torchio.RandomElasticDeformation(): augmentation_probs['random_elastic_deformation']
    })
])
romainVala commented 2 years ago

Hi

that's a tricky question and I would love to have the answer ... I remember a previous issue on this topic, but can't find it ... there was this one too #445

I guess it all depends at the end on the task and the training data ... but even knowing it would not help much to make the choice. An experimental comparison would be nice, but I guess much too computational intensive to be feasible.

So at the end, I personally follow the MRI physics to make the decision. (with the objective to have more physical realist augmentations)

for instance, MR noise is additive Gaussian noise added at the end in the Fourier domain, So I keep always the RandomNoise at the end

Adding RandomAffine or elastic deformation will reduce the noise because of the needed interpolation (so I will start with this one) Bias is really the coil sensitivity, so it change the pixel value before any mixing of motion or noise,

So I would choose something like RandomAffine / RandomElasticDeformation RandomBiasField RandomMotion RAndomNoise ZNormalisation

Ghosting and Spike are more independent (although not sure) but I would put then between bias and motion. Not sure for blur, it is meant to simulated different voxel resolution, I will put it after RandomNoise.

And Znormalisation or Salling the intensity to [0 1] should definitively be at the end because this is a transform you will also add on real data before the inference (so same thing for training ... at the end !)

I would also recommend to add some RandomGamma to improve the generalization to other scanner / modality ... ->be robust to contrast changes This one should go After affine, and before bias field

Flip has no physic meaning (just may be issue with bad image header ...) I do not use it (but as far as I understand the order should not matter)

A second question is which probability do you choose ? difficult one too ... no much to say except what I can expect in practice with real data: For 3D anatomical data I do no see that often ghosting neither spike ... in contrast to biasfield (always there) and motion (the most frequent artifact). Affine difference between subject is also always there ...

LvanderGoten commented 2 years ago

Thank you very much for the very detailed answer! It helped a lot!