fepegar / torchio

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

Unexpected transformation when using RandomAffine/RandomElasticDeformation #1214

Open sydat2701 opened 2 months ago

sydat2701 commented 2 months ago

Is there an existing issue for this?

Problem summary

Hi, thank you for your work!

I got a problem and hope you can help. My model has 2 input images and two corresponding masks for the segmentation task. I want two images transformed the same (and also masks). The image and mask inputs shape are all (1, 8, 224,224). I tried to use other transformation such as Flip, Noise, Blur, Motion,... and they worked. However, whenever I tried to use RandomAffine or RandomElasticDeformation, the image are transformed unexpectedly (I used 3Dslicer to visualize), and their output shapes are still correct. Do you have any idea for this?

This is before transformation:

bef

And this is after transformation:

after

Code for reproduction

subject = tio.Subject(
            image1=tio.ScalarImage(tensor=torch.from_numpy(images[..., 0]).unsqueeze(0)),  # First image
            mask1=tio.LabelMap(tensor=torch.from_numpy(masks[..., 0]).unsqueeze(0)),       # Corresponding mask for image1
            image2=tio.ScalarImage(tensor=torch.from_numpy(images[..., 1]).unsqueeze(0)),  # Second image
            mask2=tio.LabelMap(tensor=torch.from_numpy(masks[..., 1]).unsqueeze(0)),        # Corresponding mask for image2
            diagnosis='negative',
        )

Actual outcome

nothing

Error messages

No response

Expected outcome

nothing

System info

No response

romainVala commented 2 months ago

Hello I think it works fine, the reason of what you see is due to the fact that you have a very thin 3D volume (only 8 slice)

so if you rotate the slice plan, then you end up with a much smaller field of view (within the slice)

Affine and elastic deformation are in 3D and your data are almost in 2D. If you want to keep the full slice field of view, you need to restrict rotation within the plan only

import torchio as tio
t_aff = tio.RandomAffine(degree=(10,10,0) ) 

(you may adapt the axis set to zero depending on the axis of you slices)

for RandomElasticDeformation I do not know if one can constrain it to 2D deformation only)

fepegar commented 2 months ago

I agree with @romainVala.

for RandomElasticDeformation I do not know if one can constrain it to 2D deformation only)

Yes, you can e.g. set max. displacement to 0 along the shorter dimension.


By the way, how did you generate that volume? I suspect the voxel spacing is not correct.

sydat2701 commented 1 month ago

Hello I think it works fine, the reason of what you see is due to the fact that you have a very thin 3D volume (only 8 slice)

so if you rotate the slice plan, then you end up with a much smaller field of view (within the slice)

Affine and elastic deformation are in 3D and your data are almost in 2D. If you want to keep the full slice field of view, you need to restrict rotation within the plan only

import torchio as tio
t_aff = tio.RandomAffine(degree=(10,10,0) ) 

(you may adapt the axis set to zero depending on the axis of you slices)

for RandomElasticDeformation I do not know if one can constrain it to 2D deformation only)

Thank you! I changed as your suggestion but the error are till same. I even set all the degree to 0 such as: tio.RandomAffine(degree=(0,0,0)) but nothing change.

sydat2701 commented 1 month ago

I agree with @romainVala.

for RandomElasticDeformation I do not know if one can constrain it to 2D deformation only)

Yes, you can e.g. set max. displacement to 0 along the shorter dimension.

By the way, how did you generate that volume? I suspect the voxel spacing is not correct.

I used the resampling preprocessing step of the nnUNet project to resample the volume data to the same (1x1x1 mm) spacing. I also tried to use your "tio.ToCanonical()" first but the error still occurred whenever I use ElasticDeformation and Affine.

fepegar commented 1 month ago

Can you please share the image and a minimal working example?