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())
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.
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.,
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
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.
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]].
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.