Skip to content

Commit

Permalink
documentation: further clarify the need for consistency of axes order…
Browse files Browse the repository at this point in the history
…ing between training and inference
  • Loading branch information
FabianIsensee committed Mar 27, 2024
1 parent 927d201 commit c7f85b7
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 7 deletions.
11 changes: 8 additions & 3 deletions nnunetv2/inference/predict_from_raw_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,9 +424,14 @@ def predict_single_npy_array(self, input_image: np.ndarray, image_properties: di
"""
WARNING: SLOW. ONLY USE THIS IF YOU CANNOT GIVE NNUNET MULTIPLE IMAGES AT ONCE FOR SOME REASON.
input_image must use SimpleITK axis ordering!
(NB: if array comes from a nibabel-loaded image, you must swap the
axes of both the array *and* the spacing from [x,y,z] to [z,y,x]!)
input_image: Make sure to load the image in the way nnU-Net expects! nnU-Net is trained on a certain axis
ordering which cannot be disturbed in inference,
otherwise you will get bad results. The easiest way to achieve that is to use the same I/O class
for loading images as was used during nnU-Net preprocessing! You can find that class in your
plans.json file under the key "image_reader_writer". If you decide to freestyle, know that the
default axis ordering for medical images is the one from SimpleITK. If you load with nibabel,
you need to transpose your axes AND your spacing from [x,y,z] to [z,y,x]!
image_properties must only have a 'spacing' key!
"""
ppa = PreprocessAdapterFromNpy([input_image], [segmentation_previous_stage], [image_properties],
Expand Down
17 changes: 13 additions & 4 deletions nnunetv2/inference/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,11 @@ cons:

tldr:
- you give one image as npy array
- array must use [SimpleITK axis order](http://insightsoftwareconsortium.github.io/SimpleITK-Notebooks/Python_html/03_Image_Details.html#Conversion-between-numpy-and-SimpleITK) (see examples below)
- axes ordering must match the corresponding training data. The easiest way to achieve that is to use the same I/O class
for loading images as was used during nnU-Net preprocessing! You can find that class in your
plans.json file under the key "image_reader_writer". If you decide to freestyle, know that the
default axis ordering for medical images is the one from SimpleITK. If you load with nibabel,
you need to transpose your axes AND your spacing from [x,y,z] to [z,y,x]!
- everything is done in the main process: preprocessing, prediction, resampling, (export)
- no interlacing, slowest variant!
- ONLY USE THIS IF YOU CANNOT GIVE NNUNET MULTIPLE IMAGES AT ONCE FOR SOME REASON
Expand All @@ -161,12 +165,17 @@ cons:
- never the right choice unless you can only give a single image at a time to nnU-Net

```python
# predict a single numpy array (SimpleITK)
# predict a single numpy array (SimpleITKIO)
img, props = SimpleITKIO().read_images([join(nnUNet_raw, 'Dataset003_Liver/imagesTr/liver_63_0000.nii.gz')])
ret = predictor.predict_single_npy_array(img, props, None, None, False)

# predict a single numpy array (Nibabel with axes swapped)
img_nii = nib.load('Dataset003_Liver/imagesTr/liver_63_0000.nii.gz')
# predict a single numpy array (NibabelIO)
img, props = NibabelIO().read_images([join(nnUNet_raw, 'Dataset003_Liver/imagesTr/liver_63_0000.nii.gz')])
ret = predictor.predict_single_npy_array(img, props, None, None, False)

# The following IS NOT RECOMMENDED. Use nnunetv2.imageio!
# nibabel, we need to transpose axes and spacing to match the training axes ordering for the nnU-Net default:
nib.load('Dataset003_Liver/imagesTr/liver_63_0000.nii.gz')
img = np.asanyarray(img_nii.dataobj).transpose([2, 1, 0]) # reverse axis order to match SITK
props = {'spacing': img_nii.header.get_zooms()[::-1]} # reverse axis order to match SITK
ret = predictor.predict_single_npy_array(img, props, None, None, False)
Expand Down

0 comments on commit c7f85b7

Please sign in to comment.