Cropping an image in Jupyter notebook fails

I’m trying to crop an image in Jupyter notebook by using this code:

import SimpleITK as sitk

inputVolumeFnm  = "./test.nrrd"  
croppedImageFnm = "./testCropped.nrrd"

inIm = sitk.ReadImage(inputVolumeFnm)

cropper = sitk.CropImageFilter()
croppingBounds = [[117, 194, 95],[227, 351, 125]]
cropper.SetLowerBoundaryCropSize(croppingBounds[0])
cropper.SetUpperBoundaryCropSize(croppingBounds[1])
croppedImage = cropper.Execute(inIm) 

outIm = crop.Execute(inIm)
outIm.SetOrigin(inIm.GetOrigin())
outIm.SetDirection(inIm.GetDirection())
sitk.WriteImage(outIm, croppedImageFnm, True)

But, I’m getting this error:

Traceback (most recent call last):
  File "<string>", line 12, in <module>
  File "/users/yousefi/Downloads/Slicer-4.11.0-2020-01-07-linux-amd64/lib/Python/lib/python3.6/site-packages/SimpleITK-1.3.0rc2.dev260-py3.6-linux-x86_64.egg/SimpleITK/SimpleITK.py", line 22692, in Execute
    return _SimpleITK.CropImageFilter_Execute(self, *args)
RuntimeError: Exception thrown in SimpleITK CropImageFilter_Execute: /work/Preview/Slicer-0-build/ITK/Modules/Core/Common/src/itkPoolMultiThreader.cxx:254:
itk::ERROR: Split count is greater than number of work units!

I’m using the latest Slicer nightly build and using Python3. Any idea what’s the reason for that error?

Are you sure the file has been loaded successfully? Have you tried to load the image by specifying full path?

It seems like an error in ITK or how ITK is used. @blowekamp @thewtex do you have any clues?

We’ll upgrade ITK and SimpleITK in Slicer to latest releases within a few days, which may fix this issue.

1 Like

Yes, I believe it’s loaded successfully cause this print:

print(inIm.GetOrigin())

Shows me this:

(-177.32197570800784, -64.95606994628905, 1008.1570434570312)

One question: The crop bounds should be in extent format or range format? Extent means just integer values that corresponds to the structured points in the volumetric image but range means the 3D coordinate of points.

Extents are integer values, referring to voxel indices. See more information in this ITK discussion.

Hello,

The usage looks correct, and it certainly should produce that error.

This seems likely that it is a problem inside ITK. I’m note sure what version of ITK or SimpleITK is being used here.

You have a nice stand alone test case. Can you please try with two different stand alone versions of SimpleITK

Please report back how these versions of SimpleITK/ITK work for this test case.

1 Like

Hi @blowekamp, I just found the solution. There was two problems in my code. First I executed the crop filter twice and also I didn’t know that instead of giving the upper bound of cropped image, I need to have the upper bound of original image - upper bound of cropped image. Thank you!

What is the size in pixels of “test.nrrd”?

test.nrrd size is (512,512,144) or in terms of extent:

X extent: [0,511] (delta: 512)
Y extent: [0,511] (delta: 512)
Z extent: [0,143] (delta: 144)

and I wanted to crop this region based on its actual lower and upper bounds:

Lower bounds: [117,194,95]
Upper bounds: [227,351,125]

But I realized that crop filter take this as lower and upper bounds:

Lower bounds: [117,194,95]
Upper bounds: [511-227,511-351,143-125] = [284, 160, 18]

So, it just solved my problem and I don’t get that error anymore with same code.

I ran the following locally with the “latest” binary:

In [1]: import SimpleITK as sitk                                                                                                                        

In [2]: inIm = sitk.Image( (512,512,144), sitk.sitkUInt8)                                                                                               

In [3]:  
   ...: cropper = sitk.CropImageFilter() 
   ...: croppingBounds = [[117, 194, 95],[227, 351, 125]] 
   ...: cropper.SetLowerBoundaryCropSize(croppingBounds[0]) 
   ...: cropper.SetUpperBoundaryCropSize(croppingBounds[1]) 
   ...: croppedImage = cropper.Execute(inIm)  
   ...:                                                                                                                                                 

In [4]: print(croppedImage)                                                                                                                             
Image (0x7fbed5538090)
  RTTI typeinfo:   itk::Image<unsigned char, 3u>
  Reference Count: 1
  Modified Time: 813
  Debug: Off
  Object Name: 
  Observers: 
    none
  Source: (none)
  Source output name: (none)
  Release Data: Off
  Data Released: False
  Global Release Data: Off
  PipelineMTime: 799
  UpdateMTime: 809
  RealTimeStamp: 0 seconds 
  LargestPossibleRegion: 
    Dimension: 3
    Index: [0, 0, 0]
    Size: [168, 18446744073709551583, 18446744073709551540]
  BufferedRegion: 
    Dimension: 3
    Index: [0, 0, 0]
    Size: [168, 18446744073709551583, 18446744073709551540]
  RequestedRegion: 
    Dimension: 3
    Index: [0, 0, 0]
    Size: [168, 18446744073709551583, 18446744073709551540]

It looks like there are some signed integer and/or underflow issue going on here. SimpleITK/ITK need to be more robust with the improper parameters.

Here is a pull request to fix the issue in ITK:

2 Likes