Python sitk ExtractImageFilter -- basic usage help??

I’m sorry if I’m abit thick, but this doesn’t work.

This is the distributed SimpleITK – updated yesterday , in the Python 2.7 version on Linux

SimpleITK Version: 1.1.0 (ITK 4.13)
Compiled: Mar 26 2018 15:04:35

I tried to read documents and old mailing list entries, but I don’t find an answer, just in the past someone with a similar problem wound up using CropImageFilter instead.

Can someone clarify why this doesn’t work? I’d specifically LIKE to maintain the origin of the region as the origin of the original image and in general it could be a 4-d (time-series) image as input too so I beleive ExtractImageFilter is the right choice? I have done it in C++ with ITK 3.xx before but now I’ve been converted to Python + Simple .

Bare minimum program that doesnt work as I expect. Creates a small image and then extract a sub-image that is even smaller. Also tried with startign index not equal to zero, i.e. (5,5,5) or (1,2,3) with the same result.

  1 import SimpleITK as sitk
  2
  3 
  4 rawimg = sitk.Image(50,60,70,sitk.sitkFloat32)
  5 newim=sitk.Extract(rawimg,(20,30,40),(0,0,0))
Traceback (most recent call last):
  File "./tryextract.py", line 12, in <module>
    newim=sitk.Extract(rawimg,(20,30,40),(0,0,0))
  File "/home/kny48981/.local/lib/python2.7/site-packages/SimpleITK/SimpleITK.py", line 27140, in Extract
    return _SimpleITK.Extract(*args, **kwargs)
RuntimeError: Exception thrown in SimpleITK Extract: /tmp/SimpleITK-build/ITK-prefix/include/ITK-4.13/itkExtractImageFilter.hxx:99:
itk::ERROR: ExtractImageFilter(0x7f7eb17d8e80): Extraction Region not consistent with output image
[kny48981@i12-ws011 pycircles]$ python ./tryextract.py  /dls/i12/data/2018/cm19662-3/tmp/bubble/onebub.tif -o /scratch/SSD/robert/onebub
Traceback (most recent call last):
  File "./tryextract.py", line 5, in <module>
    newim=sitk.Extract(rawimg,(20,30,40),(0,0,0))
  File "/home/kny48981/.local/lib/python2.7/site-packages/SimpleITK/SimpleITK.py", line 27140, in Extract
    return _SimpleITK.Extract(*args, **kwargs)
RuntimeError: Exception thrown in SimpleITK Extract: /tmp/SimpleITK-build/ITK-prefix/include/ITK-4.13/itkExtractImageFilter.hxx:99:
itk::ERROR: ExtractImageFilter(0x7f8287a9e020): Extraction Region not consistent with output image

But the output image should be getting created (returned) by the filter?So how can it not be consistent???
Or what’s going on?
Especially since it worked fine in a previous program with 2d data. See below for some more code.

I tried a bit harder and used the object-oriented interface, and compare 2d and 3d, and try to set the collapse strategy as well, though I never had to set it before, (despite the documentation saying it cannot be run without setting it)

And it works in 2d but not in 3d, I really can’t see why.

  1 import SimpleITK as sitk
  2
  3 rawimg2d = sitk.Image(50,60,sitk.sitkFloat32)
  4 print rawimg2d.GetDimension()
  5 extractor2d=sitk.ExtractImageFilter()
  6 extractor2d.SetSize((20,30))
  7 extractor2d.SetIndex((5,6))
  8 extractor2d.SetDirectionCollapseToStrategy(extractor2d.DIRECTIONCOLLAPSETOIDENTITY)
  9 print "strategy, ",extractor2d.GetDirectionCollapseToStrategy()
 10 newimg2d=extractor2d.Execute(rawimg2d)
 11
 12 print "Finished 2d extractor"
 13
 14 rawimg3d = sitk.Image(50,60,70,sitk.sitkFloat32)
 15 print rawimg3d.GetDimension()
 16 extractor3d=sitk.ExtractImageFilter()
 17 extractor3d.SetSize((20,30,40))
 18 extractor3d.SetIndex((5,6,7))
 19 extractor3d.SetDirectionCollapseToStrategy(extractor3d.DIRECTIONCOLLAPSETOIDENTITY)
 20 print "strategy, ",extractor3d.GetDirectionCollapseToStrategy()
 21 newimg3d=extractor3d.Execute(rawimg3d)
 22 print "Finished 3d extractor"
 23


python ./tryextract.py  /

2
strategy,  1
Finished 2d extractor
3
strategy,  1
Traceback (most recent call last):
  File "./tryextract.py", line 21, in <module>
    newimg3d=extractor3d.Execute(rawimg3d)
  File "/home/kny48981/.local/lib/python2.7/site-packages/SimpleITK/SimpleITK.py", line 27115, in Execute
    return _SimpleITK.ExtractImageFilter_Execute(self, *args)
RuntimeError: Exception thrown in SimpleITK ExtractImageFilter_Execute: /tmp/SimpleITK-build/ITK-prefix/include/ITK-4.13/itkExtractImageFilter.hxx:99:
itk::ERROR: ExtractImageFilter(0x7fbf77727bc0): Extraction Region not consistent with output image

Hello Robert!

Thank you for reposting your question to discourse. It is much easier to post here, and provide links, and good formatting in the forum :slight_smile:

To preserve the same dimension you need to use the RegionOfInterest filter or the python bracket operator with slicing:

  1. RegionOfInterest
newim=sitk.RegionOfInterest(rawimg,(20,30,40),(0,0,0))
  1. Python Slicing
newim=rawimg[0:20,0:30,0:40]

The slicing operations can also be used to reduce dimensions, sub-sample with steps, and even flip the image all while preserving the physical location of the pixels!

There are various filters in ITK and SimpleITK that do similar things. This includes the Extract, Crop, RegionOfInterest and Slice image filters.

With SimpleITK you can’t specify the output image type, so some choices were made. What is unique about the Extract filter when compared to the others is that is can reduce the dimension of the input image to the output. So the SimpleITK Extract filter reduces the dimension by when when it can So in does 4D->3D, 3D->2D and 2D->2D ( since SimpleITK does not have 1D images). So this error message coming for itk::ExtractImageFilter is because it expect the output dimension to be 2D, therefore it expects one dimension of the size to be 0.

I’d specifically LIKE to maintain the origin of the region as the origin of the original image and in general it could be a 4-d (time-series) image as input too so I beleive ExtractImageFilter is the right choice?

All of these filters preserve the physical location of the pixels. The physical location of the region to extract does not change. So in general this should not be a concern. Since you have used C++ ITK, I’ll delve into an additional detail of SimpleITK. One simplification made, it that a SimpleITK image always has a starting index of [0]. So if the output of a ITK filter produces an image with a non-zero starting index, SimpleITK adjusted the starting index to zero, and fixes the origin appropriately. This still maintains the physical location of the pixel. It just removes a complication, that is rarely a benefit, and complicated the interface, requiring the index to be signed.

Hope that helps!

1 Like

Ok I was misled by the exceptional case where 2d only goes to 2d for this filter, so it worked in my first test which was 2d for simplicity.

Then I had no idea you could directly use Python slicing on an sitk image.
But, is it necessary to use a different method if it’s 3d->3d as for 4d->3d ? , and what results if the python slicing has a unique value eg newim=rawimg[0:20,0:30,0:40,5] , in numpy you might have to squeeze() the array to make it 3-d (which is also a bit fraught) …

With regard to the question of starting index, then is teh following from the Doxygen of itk::simple::ExtractImageFilter … um … wrong? Outdated? Or what does it mean?

The output image produced by this filter will have the same origin as the input image, while the ImageRegion of the output image will start at the starting index value provided in the ExtractRegion parameter. If you are looking for a filter that will re-compute the origin of the output image, and provide an output image region whose index is set to zeros, then you may want to use the RegionOfInterestImageFilter . The output spacing is is simply the collapsed version of the input spacing.

Probing a little it seems that Image doesn’t actually have anything called “ImageRegion”? There’s “LargestPossibleRegion”,“BufferedRegion”, and “RequestedRegion” , each of which has ‘index’, as well as “Origin” , and indeed a simple test appears (in 2-d) to show that the filters Extract, RegionofIntest, and Crop return the same values for the equivalent inputs (crop has a different meaning for its input parameters) so I was misled by this doxygen entry to think that ROI would behave differently from Extract in this case.

1 Like

The Python slicing is great! I always use it instead of those listed filters, it is flexible and has a consistent way to specify. If rawimg was a np.ndarray, then the operation rawimg[0:20,0:30,0:40,5] produces an array with shape (20,30,40) of dimension 3, reducing the dimension. In general the simpleitk [] operator is designed to behave like the numpy or standard slice based indexing.

The support for 4D images is some what limited in SimpleITK, but is should be expanded. The get_item currently does not fully support 4D images. Could you please create a simpleitk issue to add full 4D support to this method on SimpleITK GitHub.

We really should be doing better with our SimpleITK Doxygen. As of right now the description for the filters are just taken from ITK, with all the features exposed from the C++ interface. We should really mark this as coming for C++ ITK, and provide brief info about the SimpleITK simplification done, or implementation choices made. The other simplification done in SimpleITK is that “ITK streaming” is not supported, so the all these regions don’t really apply to simpleITK. There is in the ITK Software Guide about the pipeline and streaming if you are currious.

1 Like