AIM-Harvard / pyradiomics

Open-source python package for the extraction of Radiomics features from 2D and 3D images and binary masks. Support: https://discourse.slicer.org/c/community/radiomics
http://pyradiomics.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
1.15k stars 499 forks source link

Bounding box of ROI is larger than image space #408

Closed Geeks-Sid closed 6 years ago

Geeks-Sid commented 6 years ago

I've been trying to implement feature extraction with pyradiomics for the following image and the segmented output . When i run the command pyradiomics Brats18_CBICA_AAM_1_t1ce_corrected.nii.gz Brats18_CBICA_AAM_1.nii.gz --setting "correctMask:True" . I get the following error.

Image/Mask geometry mismatch, attempting to correct Mask Bounding box of ROI is larger than image space: ROI bounds (image coordinate space) ((-86.5, 85.5, 80.5), (-114.5, 46.5, 121.5)) Image Size (240, 240, 155) Image/Mask correction failed, ROI invalid (not found or outside of physical image bounds) Case-1_Image: /home/sid/Documents/pyradiomics-master/bin/Brats18_CBICA_AAM_1/Brats18_CBICA_AAM_1_t1ce_corrected.nii.gz Case-1_Mask: /home/sid/Documents/pyradiomics-master/bin/Brats18_CBICA_AAM_1/Brats18_CBICA_AAM_1.nii.gz

I've tried correct mask with other options as well as setting the tolerance high, but nothing seems to work. I have visualized them propelrly without any issues with the CaPTK tool. Is there something wrong with the mask correction or mask resampling?

fedorov commented 6 years ago

Can you please load your image and mask into a tool that is known to account for image orientation and spacing, such as 3D Slicer, and confirm the mask lines up with the image? I don't know much about the CaPTK tool. Most likely the issue is that the geometry of your mask doesn't match the image.

Geeks-Sid commented 6 years ago

Hi @fedorov , yes i have tried it in 3D slicer, but it does not interpret it at all. That's why i switched to CaPTK. I wish to fix the geometry, that is the major reason why i am trying various methods, but i have failed so far. I have tried improving tolerance, but nothing seems to be working at the moment.

JoostJM commented 6 years ago

@Geeks-Sid, I agree with @fedorov, this warning appears to be due to a mismatch in your input. More specifically, the warning message tells you that in terms of your input coordinate space, your segmentation appears to be located betwee -86.5 and -114.5 in the x direction, i.e. completely outside the image. I think in this case this is most likely due to a mismatch in the direction matrix.

For your image, this is the expected (1, 0, 0), (0, 1, 0), (0, 0, 1). For your mask, I suspect it to be (-1, 0, 0), (0, 1, 0), (0, 0, 1), but could not check this, as the link you provided for your segmentation also points to the image. If CapTK ignores this direction, or reads it out differently, that would explain why it works in CapTK.

What exactly does not work in Slicer? I was able to load your image normally. It is possible that you were able to load both the image and the segmentation, but as your segmentation is completely out-of-bounds, it is of course not displayed. You can check this by loading just the segmentation (without the image).

If the direction mismatch is the cause, you can correct this by loading (in python) your image with SimpleITK, forcibly setting the direction to that of the image (im.SetDirection(<Tuple with 9 elements>) and saving the result in a new file. Be careful when doing this, and check your results.

fedorov commented 6 years ago

@Geeks-Sid can you please correctly include the segmentation file? Currently, both of the links you included in the initial post point to the same location.

Something that may not be obvious is that if your image and label show up aligned in "some" tool, it does not necessarily mean your images have correct geometry. For example, if a given tool completely ignores origin/spacing/orientation, and just looks at the image matrices, they will line up even if geometry is initialized completely incorrectly. I don't know much about CaPTK, and how it handles geometry, so I do not have the confidence you can say geometry is correct if your segmentation and image line up in that tool.

Geeks-Sid commented 6 years ago

@fedorov @JoostJM Here are some few of my files. This is the reference file and This is the ground truth for the file and This is the segmented output that I have generated.

@fedorov As you have mentioned, I don't know how to align them to correct generated ground truth. I have tried image resampling and groundtruth tolerance change, but it doesn't seem to work right. I have tried Slicer with the image and the segmented output for visualization, but it is unable to do so. Such a behaviour is not seen in CaPTK so I am doubtful whether the resampling works or not.

fedorov commented 6 years ago

The reference file and the "ground truth" file do not cover the same field of view. Where do those files come from?

JoostJM commented 6 years ago

@fedorov, For me, the ground truth segmentation (Brats18_2013_2_1_seg.nii.gz) matches the reference image (Brats18_2013_2_1_t1ce_corrected.nii.gz) geometry. Did you perhaps switched with the generated segmentation output (Brats18_2013_2_1.nii.gz)? The generated segmentation output indeed does not match the reference image geometry:

It appears that the software used to generate the segmentation did not provide any geometry information (origin, spacing, direction), as they are defaults. Because your image is not, they appear to be misaligned. If I copy your reference image's geometry to your segmentation, it nicely lines up and looks a lot like the ground truth segmentation.

Furthermore, it struck me that for all 3 the spacing is (1, 1, 1), is this correct? In medical images, often the spacing is about 1 mm, not exactly 1 mm.

JoostJM commented 6 years ago

@Geeks-Sid, if you want to repeat my fix, try the following in python:

import SimpleITK as sitk

im = sitk.ReadImage('Brats18_2013_2_1_t1ce_corrected.nii.gz')
ma = sitk.ReadImage('Brats18_2013_2_1.nii.gz')

ma.SetDirection(im.GetDirection())
ma.SetOrigin(im.GetOrigin())

sitk.WriteImage(ma, 'Brats18_2013_2_1_correctedGeomerty.nii.gz', True)

This forces the direction and origin of your generated mask to be identical to the direction/origin of your image, but does not swap/change you matrix. Therefore, it aligns up as expected afterwards.

Be careful when using this though! Check you alignment visually to prevent unintended mirroring of your segmentation.

fedorov commented 6 years ago

For me, the ground truth segmentation (Brats18_2013_2_1_seg.nii.gz) matches the reference image (Brats18_2013_2_1_t1ce_corrected.nii.gz) geometry

You are right, I was confused.

Geeks-Sid commented 6 years ago

@JoostJM Hey, the solution you suggested worked for me. @fedorov and @JoostJM thank you for your help. So I was thinking of adding this solution to the package as

import SimpleITK as sitk

im = sitk.ReadImage('Brats18_2013_2_1_t1ce_corrected.nii.gz') ma = sitk.ReadImage('Brats18_2013_2_1.nii.gz') ma.SetDirection(im.GetDirection()) ma.SetOrigin(im.GetOrigin())

sitk.WriteImage(ma, 'Brats18_2013_2_1_correctedGeomerty.nii.gz', True)

and we could add additional parameter as sitk.WriteImage(ma, 'Brats18_2013_2_1_correctedGeomerty.nii.gz', True, like = True, refer = 'Brats18_2013_2_1_reference.nii.gz') where like = True would suggest that it should use some reference image for directions, origins, etc and refer = 'Brats18_2013_2_1_reference.nii.gz' could be the path to reference image.

Anyway I am closing this issue.

fedorov commented 6 years ago

So I was thinking of adding this solution to the package

@Geeks-Sid I would prefer not to include this into pyradiomics, since it would hide potentially critical issue from the user. If the images are not in the same space, the error should force the user to open them in a viewer and confirm the overlap. Blindly propagating image geometry to the input segmentation mask is not a good idea.

JoostJM commented 6 years ago

I agree with @fedorov.

yangyunfeng-cyber commented 1 year ago

ma.SetDirection(im.GetDirection()) ma.SetOrigin(im.GetOrigin())

if you add these , it still can't work, maybe you need to try add "ma.SetSpacing(im.GetSpacing())" behind.