Welcome to the first SimpleITK Notebook demo:

SimpleITK Image Basics

This document will give a brief orientation to the SimpleITK Image class.

First we import the SimpleITK Python module. By convention our module is imported into the shorter and more Pythonic "sitk" local name.

In [1]:
from __future__ import print_function
%matplotlib inline
import matplotlib.pyplot as plt
import SimpleITK as sitk

Image Construction

There are a variety of ways to create an image. All images' initial value is well defined as zero.

In [2]:
image = sitk.Image(256, 128, 64, sitk.sitkInt16)
image_2D = sitk.Image(64, 64, sitk.sitkFloat32)
image_2D = sitk.Image([32,32], sitk.sitkUInt32)
image_RGB = sitk.Image([128,128], sitk.sitkVectorUInt8, 3)

Pixel Types

The pixel type is represented as an enumerated type. The following is a table of the enumerated list.

sitkUInt8Unsigned 8 bit integer
sitkInt8Signed 8 bit integer
sitkUInt16Unsigned 16 bit integer
sitkInt16Signed 16 bit integer
sitkUInt32Unsigned 32 bit integer
sitkInt32Signed 32 bit integer
sitkUInt64Unsigned 64 bit integer
sitkInt64Signed 64 bit integer
sitkFloat3232 bit float
sitkFloat6464 bit float
sitkComplexFloat32complex number of 32 bit float
sitkComplexFloat64complex number of 64 bit float
sitkVectorUInt8Multi-component of unsigned 8 bit integer
sitkVectorInt8Multi-component of signed 8 bit integer
sitkVectorUInt16Multi-component of unsigned 16 bit integer
sitkVectorInt16Multi-component of signed 16 bit integer
sitkVectorUInt32Multi-component of unsigned 32 bit integer
sitkVectorInt32Multi-component of signed 32 bit integer
sitkVectorUInt64Multi-component of unsigned 64 bit integer
sitkVectorInt64Multi-component of signed 64 bit integer
sitkVectorFloat32Multi-component of 32 bit float
sitkVectorFloat64Multi-component of 64 bit float
sitkLabelUInt8RLE label of unsigned 8 bit integers
sitkLabelUInt16RLE label of unsigned 16 bit integers
sitkLabelUInt32RLE label of unsigned 32 bit integers
sitkLabelUInt64RLE label of unsigned 64 bit integers

There is also sitkUnknown, which is used for undefined or erroneous pixel ID's. It has a value of -1.

The 64-bit integer types are not available on all distributions. When not available the value is sitkUnknown.

More Information about the Image class be obtained in the Docstring

SimpleITK classes and functions have the Docstrings derived from the C++ definitions and the Doxygen documentation.

In [3]:
help(image)
Help on Image in module SimpleITK.SimpleITK object:

class Image(builtins.object)
 |  Image(*args)
 |  
 |  The Image class for SimpleITK.
 |  
 |  
 |  This Image class can represent 2D, 3D, and 4D images. The pixel types may be a
 |  scalar, a multi-component vector or a run-length-encoded (RLE)
 |  "label". The dimension, pixel type and size is specified at
 |  construction.
 |  
 |  A fundamental concept of ITK images is that they occupy physical space
 |  where the image is defined by an origin, spacing, and direction cosine
 |  matrix. The attributes are taken into consideration when doing most
 |  operations on an image. A meta-data dictionary is also associated with
 |  the image, which may contain additional fields from reading but these
 |  attributes are not propagated by image filters.
 |  
 |  The SimpleITK Image provides a single facade interface to several ITK image types.
 |  Internally, the SimpleITK Image maintains a pointer to the ITK image class, and performs reference
 |  counting and lazy copying. This means that deep copying of an image
 |  including it's buffer is delayed until the image is modified. This
 |  removes the need to use pointers to SimpleITK Image class, as copying and returning by value do not unnecessarily
 |  duplicate the data.
 |  
 |  /sa itk::Image itk::VectorImage itk::LabelMap itk::ImageBase
 |  
 |  C++ includes: sitkImage.h
 |  
 |  Methods defined here:
 |  
 |  CopyInformation(self, srcImage)
 |      CopyInformation(Image self, Image srcImage)
 |      
 |      
 |      
 |      Copy common meta-data from an image to this one.
 |      
 |      
 |      Copies the Origin, Spacing, and Direction from the source image to
 |      this image. The meta-data dictionary is not copied.
 |      
 |      It is required for the source Image's dimension and size to match, this image's attributes, otherwise an
 |      exception will be generated.
 |  
 |  EraseMetaData(self, key)
 |      EraseMetaData(Image self, std::string const & key) -> bool
 |      
 |      
 |      
 |      Remove an entry from the meta-data dictionary.
 |      
 |      
 |      Returns true, when the value exists in the dictionary and is removed,
 |      false otherwise.
 |  
 |  GetDepth(self)
 |      GetDepth(Image self) -> unsigned int
 |      
 |      
 |      
 |      Get the number of pixels the Image is in the third dimension or 0 if the Image is only 2D
 |  
 |  GetDimension(self)
 |      GetDimension(Image self) -> unsigned int
 |      
 |      
 |      
 |      Get the number of physical dimensions.
 |      
 |      Only the spatial dimensions are considered here. These are the
 |      dimensions the origin, spacing and direction cosine matrix are
 |      applicable to. This does not include the pixels' vector index as a
 |      dimension.
 |  
 |  GetDirection(self)
 |      GetDirection(Image self) -> VectorDouble
 |  
 |  GetHeight(self)
 |      GetHeight(Image self) -> unsigned int
 |      
 |      
 |      
 |      Get the number of pixels the Image is in the second dimension
 |  
 |  GetITKBase(self, *args)
 |      GetITKBase(Image self) -> itk::DataObject
 |      GetITKBase(Image self) -> itk::DataObject const *
 |  
 |  GetMetaData(self, key)
 |      GetMetaData(Image self, std::string const & key) -> std::string
 |      
 |      
 |      
 |      Get the value of a meta-data dictionary entry as a string.
 |      
 |      
 |      If the key is not in the dictionary then an exception is thrown.
 |      
 |      string types in the dictionary are returned as their native strings.
 |      Other types are printed to string before returning.
 |  
 |  GetMetaDataKeys(self)
 |      GetMetaDataKeys(Image self) -> VectorString
 |      
 |      
 |      
 |      get a vector of keys in from the meta-data dictionary
 |      
 |      
 |      Returns a vector of keys to the key/value entries in the image's meta-
 |      data dictionary. Iterate through with these keys to get the values.
 |  
 |  GetNumberOfComponentsPerPixel(self)
 |      GetNumberOfComponentsPerPixel(Image self) -> unsigned int
 |      
 |      
 |      
 |      Get the number of components for each pixel.
 |      
 |      
 |      For scalar images this methods returns 1. For vector images the number
 |      of components for each pixel is returned.
 |  
 |  GetNumberOfPixels(self)
 |      GetNumberOfPixels(Image self) -> uint64_t
 |      
 |      
 |      
 |      Get the number of pixels in the image.
 |      
 |      
 |      To Calculate the total number of values stored continuously for the
 |      image's buffer, the NumberOfPixels should be multiplied by
 |      NumberOfComponentsPerPixel in order to account for multiple component
 |      images.
 |  
 |  GetOrigin(self)
 |      GetOrigin(Image self) -> VectorDouble
 |  
 |  GetPixel(self, *idx)
 |      Returns the value of a pixel.
 |      
 |      This method takes 2 parameters in 2D: the x and y index,
 |      and 3 parameters in 3D: the x, y and z index.
 |  
 |  GetPixelAsComplexFloat64(self, idx)
 |      GetPixelAsComplexFloat64(Image self, VectorUInt32 idx) -> std::complex< double >
 |  
 |  GetPixelID(self)
 |      GetPixelID(Image self) -> itk::simple::PixelIDValueEnum
 |      
 |      
 |      
 |      Get the pixel type
 |      
 |      The pixel type is set at construction type and can not be manually
 |      changed, unless by assignment. The value may be -1 or "Unknown".
 |  
 |  GetPixelIDTypeAsString(self)
 |      GetPixelIDTypeAsString(Image self) -> std::string
 |      
 |      
 |      
 |      Return the pixel type as a human readable string value.
 |  
 |  GetPixelIDValue(self)
 |      GetPixelIDValue(Image self) -> itk::simple::PixelIDValueType
 |  
 |  GetSize(self)
 |      GetSize(Image self) -> VectorUInt32
 |      
 |      
 |      
 |      Get the number of pixels the Image is in each dimension as a std::vector. The size of the vector is
 |      equal to the number of dimensions for the image.
 |  
 |  GetSpacing(self)
 |      GetSpacing(Image self) -> VectorDouble
 |  
 |  GetWidth(self)
 |      GetWidth(Image self) -> unsigned int
 |      
 |      
 |      
 |      Get the number of pixels the Image is in the first dimension
 |  
 |  HasMetaDataKey(self, key)
 |      HasMetaDataKey(Image self, std::string const & key) -> bool
 |      
 |      
 |      
 |      Query the meta-data dictionary for the existence of a key.
 |  
 |  MakeUnique(self)
 |      MakeUnique(Image self)
 |      
 |      
 |      
 |      Performs actually coping if needed to make object unique.
 |      
 |      
 |      The Image class by default performs lazy coping and assignment. This method
 |      make sure that coping actually happens to the itk::Image pointed to is only pointed to by this object.
 |  
 |  SetDirection(self, direction)
 |      SetDirection(Image self, VectorDouble direction)
 |  
 |  SetMetaData(self, key, value)
 |      SetMetaData(Image self, std::string const & key, std::string const & value)
 |      
 |      
 |      
 |      Set an entry in the meta-data dictionary.
 |      
 |      
 |      Replaces or creates an entry in the image's meta-data dictionary.
 |  
 |  SetOrigin(self, origin)
 |      SetOrigin(Image self, VectorDouble origin)
 |  
 |  SetPixel(self, *args)
 |      Sets the value of a pixel.
 |      
 |      This method takes 3 parameters in 2D: the x and y index then the value,
 |      and 4 parameters in 3D: the x, y and z index then the value.
 |  
 |  SetPixelAsComplexFloat64(self, idx, v)
 |      SetPixelAsComplexFloat64(Image self, VectorUInt32 idx, std::complex< double > const v)
 |  
 |  SetSpacing(self, spacing)
 |      SetSpacing(Image self, VectorDouble spacing)
 |  
 |  TransformContinuousIndexToPhysicalPoint(self, index)
 |      TransformContinuousIndexToPhysicalPoint(Image self, VectorDouble index) -> VectorDouble
 |      
 |      
 |      
 |      Transform continuous index to physical point
 |  
 |  TransformIndexToPhysicalPoint(self, index)
 |      TransformIndexToPhysicalPoint(Image self, VectorInt64 index) -> VectorDouble
 |      
 |      
 |      
 |      Transform index to physical point
 |  
 |  TransformPhysicalPointToContinuousIndex(self, point)
 |      TransformPhysicalPointToContinuousIndex(Image self, VectorDouble point) -> VectorDouble
 |      
 |      
 |      
 |      Transform physical point to continuous index
 |  
 |  TransformPhysicalPointToIndex(self, point)
 |      TransformPhysicalPointToIndex(Image self, VectorDouble point) -> VectorInt64
 |      
 |      
 |      
 |      Transform physical point to index
 |  
 |  __GetPixelAsComplexFloat32__(self, idx)
 |      __GetPixelAsComplexFloat32__(Image self, VectorUInt32 idx) -> std::complex< float >
 |  
 |  __GetPixelAsDouble__(self, idx)
 |      __GetPixelAsDouble__(Image self, VectorUInt32 idx) -> double
 |  
 |  __GetPixelAsFloat__(self, idx)
 |      __GetPixelAsFloat__(Image self, VectorUInt32 idx) -> float
 |  
 |  __GetPixelAsInt16__(self, idx)
 |      __GetPixelAsInt16__(Image self, VectorUInt32 idx) -> int16_t
 |  
 |  __GetPixelAsInt32__(self, idx)
 |      __GetPixelAsInt32__(Image self, VectorUInt32 idx) -> int32_t
 |  
 |  __GetPixelAsInt64__(self, idx)
 |      __GetPixelAsInt64__(Image self, VectorUInt32 idx) -> int64_t
 |  
 |  __GetPixelAsInt8__(self, idx)
 |      __GetPixelAsInt8__(Image self, VectorUInt32 idx) -> int8_t
 |  
 |  __GetPixelAsUInt16__(self, idx)
 |      __GetPixelAsUInt16__(Image self, VectorUInt32 idx) -> uint16_t
 |  
 |  __GetPixelAsUInt32__(self, idx)
 |      __GetPixelAsUInt32__(Image self, VectorUInt32 idx) -> uint32_t
 |  
 |  __GetPixelAsUInt64__(self, idx)
 |      __GetPixelAsUInt64__(Image self, VectorUInt32 idx) -> uint64_t
 |  
 |  __GetPixelAsUInt8__(self, idx)
 |      __GetPixelAsUInt8__(Image self, VectorUInt32 idx) -> uint8_t
 |  
 |  __GetPixelAsVectorFloat32__(self, idx)
 |      __GetPixelAsVectorFloat32__(Image self, VectorUInt32 idx) -> VectorFloat
 |  
 |  __GetPixelAsVectorFloat64__(self, idx)
 |      __GetPixelAsVectorFloat64__(Image self, VectorUInt32 idx) -> VectorDouble
 |  
 |  __GetPixelAsVectorInt16__(self, idx)
 |      __GetPixelAsVectorInt16__(Image self, VectorUInt32 idx) -> VectorInt16
 |  
 |  __GetPixelAsVectorInt32__(self, idx)
 |      __GetPixelAsVectorInt32__(Image self, VectorUInt32 idx) -> VectorInt32
 |  
 |  __GetPixelAsVectorInt64__(self, idx)
 |      __GetPixelAsVectorInt64__(Image self, VectorUInt32 idx) -> VectorInt64
 |  
 |  __GetPixelAsVectorInt8__(self, idx)
 |      __GetPixelAsVectorInt8__(Image self, VectorUInt32 idx) -> VectorInt8
 |  
 |  __GetPixelAsVectorUInt16__(self, idx)
 |      __GetPixelAsVectorUInt16__(Image self, VectorUInt32 idx) -> VectorUInt16
 |  
 |  __GetPixelAsVectorUInt32__(self, idx)
 |      __GetPixelAsVectorUInt32__(Image self, VectorUInt32 idx) -> VectorUInt32
 |  
 |  __GetPixelAsVectorUInt64__(self, idx)
 |      __GetPixelAsVectorUInt64__(Image self, VectorUInt32 idx) -> VectorUInt64
 |  
 |  __GetPixelAsVectorUInt8__(self, idx)
 |      __GetPixelAsVectorUInt8__(Image self, VectorUInt32 idx) -> VectorUInt8
 |  
 |  __SetPixelAsComplexFloat32__(self, idx, v)
 |      __SetPixelAsComplexFloat32__(Image self, VectorUInt32 idx, std::complex< float > const v)
 |  
 |  __SetPixelAsDouble__(self, idx, v)
 |      __SetPixelAsDouble__(Image self, VectorUInt32 idx, double v)
 |  
 |  __SetPixelAsFloat__(self, idx, v)
 |      __SetPixelAsFloat__(Image self, VectorUInt32 idx, float v)
 |  
 |  __SetPixelAsInt16__(self, idx, v)
 |      __SetPixelAsInt16__(Image self, VectorUInt32 idx, int16_t v)
 |  
 |  __SetPixelAsInt32__(self, idx, v)
 |      __SetPixelAsInt32__(Image self, VectorUInt32 idx, int32_t v)
 |  
 |  __SetPixelAsInt64__(self, idx, v)
 |      __SetPixelAsInt64__(Image self, VectorUInt32 idx, int64_t v)
 |  
 |  __SetPixelAsInt8__(self, idx, v)
 |      __SetPixelAsInt8__(Image self, VectorUInt32 idx, int8_t v)
 |  
 |  __SetPixelAsUInt16__(self, idx, v)
 |      __SetPixelAsUInt16__(Image self, VectorUInt32 idx, uint16_t v)
 |  
 |  __SetPixelAsUInt32__(self, idx, v)
 |      __SetPixelAsUInt32__(Image self, VectorUInt32 idx, uint32_t v)
 |  
 |  __SetPixelAsUInt64__(self, idx, v)
 |      __SetPixelAsUInt64__(Image self, VectorUInt32 idx, uint64_t v)
 |  
 |  __SetPixelAsUInt8__(self, idx, v)
 |      __SetPixelAsUInt8__(Image self, VectorUInt32 idx, uint8_t v)
 |  
 |  __SetPixelAsVectorFloat32__(self, idx, v)
 |      __SetPixelAsVectorFloat32__(Image self, VectorUInt32 idx, VectorFloat v)
 |  
 |  __SetPixelAsVectorFloat64__(self, idx, v)
 |      __SetPixelAsVectorFloat64__(Image self, VectorUInt32 idx, VectorDouble v)
 |  
 |  __SetPixelAsVectorInt16__(self, idx, v)
 |      __SetPixelAsVectorInt16__(Image self, VectorUInt32 idx, VectorInt16 v)
 |  
 |  __SetPixelAsVectorInt32__(self, idx, v)
 |      __SetPixelAsVectorInt32__(Image self, VectorUInt32 idx, VectorInt32 v)
 |  
 |  __SetPixelAsVectorInt64__(self, idx, v)
 |      __SetPixelAsVectorInt64__(Image self, VectorUInt32 idx, VectorInt64 v)
 |  
 |  __SetPixelAsVectorInt8__(self, idx, v)
 |      __SetPixelAsVectorInt8__(Image self, VectorUInt32 idx, VectorInt8 v)
 |  
 |  __SetPixelAsVectorUInt16__(self, idx, v)
 |      __SetPixelAsVectorUInt16__(Image self, VectorUInt32 idx, VectorUInt16 v)
 |  
 |  __SetPixelAsVectorUInt32__(self, idx, v)
 |      __SetPixelAsVectorUInt32__(Image self, VectorUInt32 idx, VectorUInt32 v)
 |  
 |  __SetPixelAsVectorUInt64__(self, idx, v)
 |      __SetPixelAsVectorUInt64__(Image self, VectorUInt32 idx, VectorUInt64 v)
 |  
 |  __SetPixelAsVectorUInt8__(self, idx, v)
 |      __SetPixelAsVectorUInt8__(Image self, VectorUInt32 idx, VectorUInt8 v)
 |  
 |  __abs__(self)
 |  
 |  __add__(self, other)
 |  
 |  __and__(self, other)
 |  
 |  __del__ lambda self
 |  
 |  __div__(self, other)
 |  
 |  __eq__(self, other)
 |      Return self==value.
 |  
 |  __floordiv__(self, other)
 |  
 |  __ge__(self, other)
 |      Return self>=value.
 |  
 |  __getattr__ lambda self, name
 |  
 |  __getitem__(self, idx)
 |      Get an pixel value or a sliced image.
 |      
 |      This operator implements basic indexing where idx is
 |      arguments or a squence of integers the same dimension as
 |      the image. The result will be a pixel value from that
 |      index.
 |      
 |      Multi-dimension extended slice based indexing is also
 |      implemented. The return is a copy of a new image. The
 |      standard sliced based indices are supported including
 |      negative indices, to indicate location relative to the
 |      end, along with negative step sized to indicate reversing
 |      of direction.
 |      
 |      If the length of idx is less than the number of dimension
 |      of the image it will be padded with the defaults slice
 |      ":".
 |      
 |      A 2D image can be extracted from a 3D image by providing
 |      one argument being an integer instead of a slice.
 |  
 |  __gt__(self, other)
 |      Return self>value.
 |  
 |  __iadd__(self, other)
 |      # NOTE: the __i*__ methods are not implemented because there
 |      # currently in no way to make the underlying filters run
 |      # inplace. But python will implement a default version based
 |      # on the standard method
 |  
 |  __init__(self, *args)
 |      __init__(itk::simple::Image self) -> Image
 |      __init__(itk::simple::Image self, Image img) -> Image
 |      __init__(itk::simple::Image self, unsigned int width, unsigned int height, itk::simple::PixelIDValueEnum valueEnum) -> Image
 |      __init__(itk::simple::Image self, unsigned int width, unsigned int height, unsigned int depth, itk::simple::PixelIDValueEnum valueEnum) -> Image
 |      __init__(itk::simple::Image self, VectorUInt32 size, itk::simple::PixelIDValueEnum valueEnum, unsigned int numberOfComponents=0) -> Image
 |  
 |  __invert__(self)
 |  
 |  __iter__(self)
 |  
 |  __le__(self, other)
 |      Return self<=value.
 |  
 |  __len__(self)
 |  
 |  __lt__(self, other)
 |      Return self<value.
 |  
 |  __mod__(self, other)
 |  
 |  __mul__(self, other)
 |  
 |  __ne__(self, other)
 |      Return self!=value.
 |  
 |  __neg__(self)
 |  
 |  __or__(self, other)
 |  
 |  __pos__(self)
 |  
 |  __pow__(self, other)
 |  
 |  __radd__(self, other)
 |  
 |  __rand__(self, other)
 |  
 |  __rdiv__(self, other)
 |  
 |  __repr__ = _swig_repr(self)
 |  
 |  __rfloordiv__(self, other)
 |  
 |  __rmul__(self, other)
 |  
 |  __ror__(self, other)
 |  
 |  __rpow__(self, other)
 |  
 |  __rsub__(self, other)
 |  
 |  __rtruediv__(self, other)
 |  
 |  __rxor__(self, other)
 |  
 |  __setattr__ lambda self, name, value
 |  
 |  __setitem__(self, idx, value)
 |      Sets the pixel value at index idx to value.
 |      
 |      The dimension of idx should match that of the image.
 |  
 |  __str__(self)
 |      __str__(Image self) -> std::string
 |  
 |  __sub__(self, other)
 |  
 |  __truediv__(self, other)
 |  
 |  __xor__(self, other)
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __swig_destroy__ = delete_Image(...)
 |      delete_Image(Image self)
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __hash__ = None
 |  
 |  __swig_getmethods__ = {}
 |  
 |  __swig_setmethods__ = {}

Accessing Attributes

If you are familiar with ITK, then these methods will follow your expectations:

In [4]:
print(image.GetSize())
print(image.GetOrigin())
print(image.GetSpacing())
print(image.GetDirection())
print(image.GetNumberOfComponentsPerPixel())
(256, 128, 64)
(0.0, 0.0, 0.0)
(1.0, 1.0, 1.0)
(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)
1

Note: The starting index of a SimpleITK Image is always 0. If the output of an ITK filter has non-zero starting index, then the index will be set to 0, and the origin adjusted accordingly.

The size of the image's dimensions have explicit accessors:

In [5]:
print(image.GetWidth())
print(image.GetHeight())
print(image.GetDepth())
256
128
64

Since the dimension and pixel type of a SimpleITK image is determined at run-time accessors are needed.

In [6]:
print(image.GetDimension())
print(image.GetPixelIDValue())
print(image.GetPixelIDTypeAsString())
3
2
16-bit signed integer

What is the depth of a 2D image?

In [7]:
print(image_2D.GetSize())
print(image_2D.GetDepth())
(32, 32)
0

What is the dimension and size of a Vector image?

In [8]:
print(image_RGB.GetDimension())
print(image_RGB.GetSize())
2
(128, 128)
In [9]:
print(image_RGB.GetNumberOfComponentsPerPixel())
3

For certain file types such as DICOM, additional information about the image is contained in the meta-data dictionary.

In [10]:
for key in image.GetMetaDataKeys():
        print("\"{0}\":\"{1}\"".format(key, image.GetMetaData(key)))

Accessing Pixels

There are the member functions GetPixel and SetPixel which provides an ITK-like interface for pixel access.

In [11]:
help(image.GetPixel)
Help on method GetPixel in module SimpleITK.SimpleITK:

GetPixel(*idx) method of SimpleITK.SimpleITK.Image instance
    Returns the value of a pixel.
    
    This method takes 2 parameters in 2D: the x and y index,
    and 3 parameters in 3D: the x, y and z index.

In [12]:
print(image.GetPixel(0, 0, 0))
image.SetPixel(0, 0, 0, 1)
print(image.GetPixel(0, 0, 0))
0
1
In [13]:
print(image[0,0,0])
image[0,0,0] = 10
print(image[0,0,0])
1
10

Conversion between numpy and SimpleITK

In [14]:
nda = sitk.GetArrayFromImage(image)
print(nda)
[[[10  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  ...
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]]

 [[ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  ...
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]]

 [[ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  ...
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]]

 ...

 [[ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  ...
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]]

 [[ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  ...
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]]

 [[ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  ...
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]
  [ 0  0  0 ...  0  0  0]]]
In [15]:
help(sitk.GetArrayFromImage)
Help on function GetArrayFromImage in module SimpleITK.SimpleITK:

GetArrayFromImage(image)
    Get a NumPy ndarray from a SimpleITK Image.
    
    This is a deep copy of the image buffer and is completely safe and without potential side effects.

In [16]:
# Get a view of the image data as a numpy array, useful for display
nda = sitk.GetArrayViewFromImage(image)
In [17]:
nda = sitk.GetArrayFromImage(image_RGB)
img = sitk.GetImageFromArray(nda)
img.GetSize()
Out[17]:
(3, 128, 128)
In [18]:
help(sitk.GetImageFromArray)
Help on function GetImageFromArray in module SimpleITK.SimpleITK:

GetImageFromArray(arr, isVector=None)
    Get a SimpleITK Image from a numpy array. If isVector is True, then the Image will have a Vector pixel type, and the last dimension of the array will be considered the component index. By default when isVector is None, 4D images are automatically considered 3D vector images.

In [19]:
img = sitk.GetImageFromArray(nda, isVector=True)
print(img)
VectorImage (0x7f9112f17580)
  RTTI typeinfo:   itk::VectorImage<unsigned char, 2u>
  Reference Count: 1
  Modified Time: 803
  Debug: Off
  Object Name: 
  Observers: 
    none
  Source: (none)
  Source output name: (none)
  Release Data: Off
  Data Released: False
  Global Release Data: Off
  PipelineMTime: 0
  UpdateMTime: 0
  RealTimeStamp: 0 seconds 
  LargestPossibleRegion: 
    Dimension: 2
    Index: [0, 0]
    Size: [128, 128]
  BufferedRegion: 
    Dimension: 2
    Index: [0, 0]
    Size: [128, 128]
  RequestedRegion: 
    Dimension: 2
    Index: [0, 0]
    Size: [128, 128]
  Spacing: [1, 1]
  Origin: [0, 0]
  Direction: 
1 0
0 1

  IndexToPointMatrix: 
1 0
0 1

  PointToIndexMatrix: 
1 0
0 1

  Inverse Direction: 
1 0
0 1

  VectorLength: 3
  PixelContainer: 
    ImportImageContainer (0x7f9112f17750)
      RTTI typeinfo:   itk::ImportImageContainer<unsigned long, unsigned char>
      Reference Count: 1
      Modified Time: 804
      Debug: Off
      Object Name: 
      Observers: 
        none
      Pointer: 0x120f22000
      Container manages memory: true
      Size: 49152
      Capacity: 49152

The order of index and dimensions need careful attention during conversion

ITK's Image class does not have a bracket operator. It has a GetPixel which takes an ITK Index object as an argument, which is ordered as (x,y,z). This is the convention that SimpleITK's Image class uses for the GetPixel method and slicing operator as well. In numpy, an array is indexed in the opposite order (z,y,x). Also note that the access to channels is different. In SimpleITK you do not access the channel directly, rather the pixel value representing all channels for the specific pixel is returned and you then access the channel for that pixel. In the numpy array you are accessing the channel directly.

In [20]:
import numpy as np

multi_channel_3Dimage = sitk.Image([2,4,8], sitk.sitkVectorFloat32, 5)
x = multi_channel_3Dimage.GetWidth() - 1
y = multi_channel_3Dimage.GetHeight() - 1
z = multi_channel_3Dimage.GetDepth() - 1
multi_channel_3Dimage[x,y,z] = np.random.random(multi_channel_3Dimage.GetNumberOfComponentsPerPixel())

nda = sitk.GetArrayFromImage(multi_channel_3Dimage)

print("Image size: " + str(multi_channel_3Dimage.GetSize()))
print("Numpy array size: " + str(nda.shape))

# Notice the index order and channel access are different:
print("First channel value in image: " + str(multi_channel_3Dimage[x,y,z][0]))
print("First channel value in numpy array: " + str(nda[z,y,x,0]))
Image size: (2, 4, 8)
Numpy array size: (8, 4, 2, 5)
First channel value in image: 0.710931658744812
First channel value in numpy array: 0.71093166

Are we still dealing with Image, because I haven't seen one yet...

While SimpleITK does not do visualization, it does contain a built in Show method. This function writes the image out to disk and than launches a program for visualization. By default it is configured to use ImageJ, because it is readily supports all the image types which SimpleITK has and load very quickly. However, it's easily customizable by setting environment variables.

In [21]:
sitk.Show(image)
In [22]:
sitk.Show?

By converting into a numpy array, matplotlib can be used for visualization for integration into the scientific python environment.

In [23]:
%matplotlib inline
import matplotlib.pyplot as plt
In [24]:
z = 0
slice = sitk.GetArrayViewFromImage(image)[z,:,:]
plt.imshow(slice)
Out[24]:
<matplotlib.image.AxesImage at 0x103abaf98>