Python wrapped itk.Image - What type to use for int

I was trying to convert a DICOM stack to a NifTI in Python when I realized itk.Image is not wrapped for pixel type int. I installed itk through Anaconda.

It is my understanding that if I defined a variable of type int in C, the size would be platform dependant. However, it wouldn’t make sense for the image data pixel type to be platform dependant.

Can I assume that if an image has pixel type int I can read it in as type short? When I read the DICOM in as type short, the data looks correct when rendered. I just want to know if this is a fluke.

Here is how I determine the pixel type:

# Try to get the ImageIO given the file name
imageIO = itk.ImageIOFactory.CreateImageIO(file_name, itk.ImageIOFactory.ReadMode)
if imageIO is None:
    return None
imageIO.SetFileName(file_name)
imageIO.ReadImageInformation()

# Get pixel type
pixel_type_as_string = imageIO.GetComponentTypeAsString(imageIO.GetComponentType())

Hello,

Most modern desktop systems are in agreement with most intrinsic types unsigned char, short, int, long long. The inconsistent types are long and the signless of char. Additionally, embedded system and super computer type systems may not agree.

With ITK when you read an image, into a type that is different that the type in the file the image is automatically scaled for the different potential range of the pixel type. Try reading into a “unsigned char” as an example. The range should preserved but the accuracy is loss. Reading the image into double would ensure no loss of information.

I believe you are working on with ITK for Python for other reasons, but as a developer of SimpleITK I must toute that SimpleITK has instantiated the itk image, and IO with all the fixed width integer pixel types, include uint16_t, int16_t, uint32_t, int32_t (and many others). Additionally the default sitk::ReadImage behavior is to read the image with the exact same pixel size as reported by the ImageIO. These features may make it easier to do some accurate image munging before the rest of you image analysis. Additionally, in the latest development version we have added the ability to read the meta-information with out the bulk image data.

3 Likes

The vast majority of DICOM image files are stored as short, unsigned short, or unsigned char, so it is likely that short is the correct pixel type to use in this case.

To automatically read in an image regardless of pixel type with ITK’s Python wrapping, use itk.imread. E.g.,

image = itk.imread("input_filename.png")
print(type(image))

will automatically load the image with the native pixel type. This is explained in greater detail in this blog post.

1 Like

Ok, excellent information! This fills in a lot of holes. I was originally going to use itk.imread to get the filetype to pass into itk.ImageSeriesReader. I got this error though.

>>> dicom_slice_file_name = 'IM-0001.dcm'
>>> image = itk.imread(dicom_slice_file_name)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/babesler/anaconda3/envs/reg/lib/python2.7/site-packages/itkExtras.py", line 445, in imread
    reader = itk.ImageFileReader.New(FileName=fileName)
  File "/Users/babesler/anaconda3/envs/reg/lib/python2.7/site-packages/itkTemplate.py", line 383, in New
    return self._NewImageFileReader(*args, **kwargs)
  File "/Users/babesler/anaconda3/envs/reg/lib/python2.7/site-packages/itkTemplate.py", line 433, in _NewImageFileReader
    ImageType = itk.Image[PixelType, dimension]
  File "/Users/babesler/anaconda3/envs/reg/lib/python2.7/site-packages/itkTemplate.py", line 274, in __getitem__
    (str(parameters), self.__name__))
KeyError: 'itkTemplate : No template (<itkCType signed int>, 3) for the itk::Image class'

You can see I have a signed int DICOM image. itk.Image is not wrapped for that type. (I also tried playing with ImageSeriesReader only to arrive at the same problem, obviously).

It’s obvious now, but the itkImageReader is templated over the output type. It makes sense that you can read the data directly into another format. Maybe SimpleITK is the way to go @blowekamp :stuck_out_tongue:

Summary

  • Even though itk.Image isn’t wrapped for all scalar types, you can still read all types by changing the output image. The data will be rescaled to the output pixel range. Read as double for no loss of information.
  • An unsigned int DICOM file is rare.

Thanks @blowekamp @matt.mccormick!

3 Likes

I got a similar issue with the following toy example

import itk                                                                           
from pydicom.data import get_testdata_files                                          
filename = get_testdata_files('CT_small.dcm')[0]                                     
img = itk.imread(filename) 

KeyError: 'itkTemplate : No template (<itkCType unsigned int>, 3) for the itk::Image class'

When opening with pydicom, the type is recognized as short (np.int16). What would be the reason to not support this type when opening with imread?

We should improve this error message, by making it more informative and suggesting a way to resolve the issue.

Currently, int and unsigned int are not wrapped to keep the package binary size reasonable.

1 Like

I know this thread is old, but I’m also in need of a Python-wrapped itk.Image[unsigned int, 3] for handling labeled brain atlas images.

Is there a way to extend the Python-wrapped types when compiling ITK from source? Specifically, I think I would need itk.ImageFileReader[itk.Image[itk.UL, 3]].

Hi @beastwood,

Do unsigned short pixels address this use case? The image can be read with:

image = itk.imread(file_name, itk.US)

Yes, to wrap for 64-bit unsigned integers set the CMake Configuration option ITK_WRAP_unsigned_long_long:BOOL=ON.

A follow-up note, this error message was improved in recent versions of ITK.

1 Like

Thank you, @matt.mccormick!

Unfortunately, no, the labeled image data I’m working with is 32-bit unsigned. It doesn’t have 2^16 unique values, but it does contain values greater than 2^16.

I tried compiling ITK with python wrapping but ran into many errors that made me think I have an inconsistency in CMake configuration. For now I can use SimpleITK, but I like the way the ITK python API is going, so I may come back to it in the future.

Thanks so much for your help.
Brian

1 Like

This patch will enable reading 64-bit unsigned:

Thank you so much, Matt! This is great.

1 Like