import itk
from packaging.version import parse
from importlib.metadata import version
if parse(version('itk')) < parse('5.3'):
raise ValueError("ITK greater than version 5.3.0 is required for this notebook")
from itkwidgets import view
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
image = itk.imread("data/KitwareITK.jpg")
view(image)
<itkwidgets.viewer.Viewer at 0x7ff484101210>
array = itk.array_from_image(image)
print(array[1, 1])
[51 56 60]
Let go the other way around: NumPy array to an ITK image. First, we create an array with some values.
def make_gaussian(size, fwhm=3, center=None):
"""Make a square gaussian kernel.
size is the length of a side of the square
fwhm is full-width-half-maximum, which
can be considered an effective radius.
"""
x = np.arange(0, size, 1, np.float32)
y = x[:, np.newaxis]
if center is None:
x0 = y0 = size // 2
else:
x0 = center[0]
y0 = center[1]
return np.exp(-4 * np.log(2) * ((x - x0) ** 2 + (y - y0) ** 2) / fwhm**2)
array = make_gaussian(11)
Let's look at the array. We use matplotlib
or itkwidgets.view
to do this.
plt.gray()
plt.imshow(array)
plt.axis("off")
(-0.5, 10.5, 10.5, -0.5)
image = itk.image_from_array(array)
view(image, cmap="Grayscale", interpolation=False)
<itkwidgets.viewer.Viewer at 0x7ff483a10510>
image = itk.imread("data/CBCT-TextureInput.png", itk.F)
# %load solutions/2_ITK_in_Python_answers_Exercise1.py
So far we have used
itk.array_from_image()
itk.image_from_array()
.Also available:
itk.array_view_from_image()
itk.image_view_from_array()
You can see the keyword view in both the names of these functions.
How to they differ in their behavior?
Let's compare the result of itk.array_view_from_image()
and itk.array_from_image()
.
gaussian = itk.gaussian_image_source(size=11, sigma=3, scale=100, mean=[5, 5])
arr_view_gaussian = itk.array_view_from_image(gaussian)
arr_gaussian = itk.array_from_image(gaussian)
gaussian.SetPixel([5, 5], 0)
plt.subplot(1, 2, 1)
plt.imshow(arr_view_gaussian)
plt.title("View")
plt.subplot(1, 2, 2)
plt.imshow(arr_gaussian)
plt.title("Copy")
Text(0.5, 1.0, 'Copy')
--
--
# %load solutions/2_ITK_and_NumPy_answers_Exercise2.py
help(itk.Image)
Help on itkTemplate in module itk.support.template_class object: itk::Image = class itkTemplate(collections.abc.Mapping) | itk::Image(new_object_name: str) -> 'itkTemplate' | | This class manages access to available template arguments of a C++ class. | | This class is generic and does not give help on the methods available in | the instantiated class. To get help on a specific ITK class, instantiate an | object of that class. | | e.g.: median = itk.MedianImageFilter[ImageType, ImageType].New() | help(median) | | There are two ways to access types: | | 1. With a dict interface. The user can manipulate template parameters | similarly to C++, with the exception that the available parameters sets are | chosen at compile time. It is also possible, with the dict interface, to | explore the available parameters sets. | 2. With object attributes. The user can easily find the available parameters | sets by pressing tab in interpreter like ipython | | Method resolution order: | itkTemplate | collections.abc.Mapping | collections.abc.Collection | collections.abc.Sized | collections.abc.Iterable | collections.abc.Container | builtins.object | | Methods defined here: | | GetTypes(self) | Helper method which prints out the available template parameters. | | GetTypesAsList(self) | Helper method which returns the available template parameters. | | New(self, *args, **kwargs) | Instantiate the template with a type implied from its input. | | Template type specification can be avoided by assuming that the type's | first template argument should have the same type as its primary input. | This is generally true. If it is not true, then specify the types | explicitly. | | For example, instead of the explicit type specification:: | | median = itk.MedianImageFilter[ImageType, ImageType].New() | median.SetInput(reader.GetOutput()) | | call:: | | median = itk.MedianImageFilter.New(Input=reader.GetOutput()) | | or, the shortened:: | | median = itk.MedianImageFilter.New(reader.GetOutput()) | | or: | | median = itk.MedianImageFilter.New(reader) | | __add__(self, paramSetString: str, cl: Callable[..., Any]) -> None | Add a new argument set and the resulting class to the template. | | paramSetString is the C++ string which defines the parameters set. | cl is the class which corresponds to the couple template-argument set. | | __call__(self, *args, **kwargs) | Deprecated procedural interface function. | | Use snake case function instead. This function is now | merely a wrapper around the snake case function (more | specifically around `__internal_call__()` to avoid | creating a new instance twice). | | Create a process object, update with the inputs and | attributes, and return the result. | | The syntax is the same as the one used in New(). | | UpdateLargestPossibleRegion() is execute and the current output, | or tuple of outputs if there is more than one, is returned. | | For example, | | outputImage = itk.MedianImageFilter(inputImage, Radius=(1,2)) | | __contains__(self, key) | | __dir__(self) | Returns the list of the attributes available in the current template. | | This loads all the modules that might be required by this template first, | and then returns the list of attributes. It is used when dir() is called | or when it tries to autocomplete attribute names. | | __find_param__(self, paramSetString) -> List[Any] | Find the parameters of the template. | | paramSetString is the C++ string which defines the parameters set. | | __find_param__ returns a list of itk classes, itkCType, and/or numbers | which correspond to the parameters described in paramSetString. | The parameters MUST have been registered before calling this method, | or __find_param__ will return a string and not the wanted object, and | will display a warning. Registration order is important. | | This method is not static only to be able to display the template name | in the warning. | | __getattr__(self, attr) | Support for lazy loading. | | __getitem__(self, parameters) -> Callable[..., Any] | Return the class which corresponds to the given template parameters. | | parameters can be: | - a single parameter (Ex: itk.Index[2]) | - a list of elements (Ex: itk.Image[itk.UC, 2]) | | __getnewargs_ex__(self) | Return arguments for __new__. | Required by the Pickle protocol. | | __hash__(self) | Overloads `hash()` when called on an `itkTemplate` object. | | Identify with the __name__, e.g. `itk.Image.__name__` is `itk::Image`. | Used by frozenset construction in typing._GenericAlias | | __instancecheck__(self, instance) -> bool | Overloads `isinstance()` when called on an `itkTemplate` object. | | This function allows to compare an object to a filter without | specifying the actual template arguments of the class. It will | test all available template parameters that have been wrapped | and return `True` if one that corresponds to the object is found. | | __iter__(self) | # everything after this comment is for dict interface | # and is a copy/paste from DictMixin | # only methods to edit dictionary are not there | | __len__(self) | | __local__init__(self, new_object_name: str) -> None | Can not have a __init__ because we must use __new__ | so that the singleton takes preference. | Use this to define the class member elements | | __repr__(self) -> str | Return repr(self). | | get(self, key, default=None) | D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None. | | items(self) | D.items() -> a set-like object providing a view on D's items | | keys(self) | D.keys() -> a set-like object providing a view on D's keys | | values(self) | D.values() -> an object providing a view on D's values | | ---------------------------------------------------------------------- | Static methods defined here: | | __new__(cls, new_object_name: str) -> 'itkTemplate' | Create and return a new object. See help(type) for accurate signature. | | normalizeName(name: str) -> str | Normalize the class name to remove ambiguity | | This function removes the white spaces in the name, and also | remove the pointer declaration "*" (it have no sense in python) | | registerNoTpl(name: str, cl: 'itkTemplate') -> None | Register a class without template | | It can seem not useful to register classes without template (and it wasn't | useful until the SmartPointer template was generated), but those classes | can be used as template argument of classes with template. | | ---------------------------------------------------------------------- | Data descriptors defined here: | | __dict__ | dictionary for instance variables | | __weakref__ | list of weak references to the object | | ---------------------------------------------------------------------- | Data and other attributes defined here: | | __abstractmethods__ = frozenset() | | ---------------------------------------------------------------------- | Methods inherited from collections.abc.Mapping: | | __eq__(self, other) | Return self==value. | | ---------------------------------------------------------------------- | Data and other attributes inherited from collections.abc.Mapping: | | __reversed__ = None | | ---------------------------------------------------------------------- | Class methods inherited from collections.abc.Collection: | | __subclasshook__(C) from abc.ABCMeta | Abstract classes can override this to customize issubclass(). | | This is invoked early on by abc.ABCMeta.__subclasscheck__(). | It should return True, False or NotImplemented. If it returns | NotImplemented, the normal algorithm is used. Otherwise, it | overrides the normal algorithm (and the outcome is cached). | | ---------------------------------------------------------------------- | Class methods inherited from collections.abc.Iterable: | | __class_getitem__ = GenericAlias(...) from abc.ABCMeta | Represent a PEP 585 generic type | | E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
dtype
in NumPyimport numpy
numpy.array([0, 0], dtype=float)
array([0., 0.])
# A pixel Index is templated over the image dimension
IndexType = itk.Index[3]
index = IndexType()
print(index)
itkIndex3 ([0, 0, 0])
ImageType = itk.Image[itk.ctype("float"), 2]
my_image = ImageType.New()
print(my_image)
Image (0x561be6e990f0) RTTI typeinfo: itk::Image<float, 2u> Reference Count: 1 Modified Time: 868 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: [0, 0] BufferedRegion: Dimension: 2 Index: [0, 0] Size: [0, 0] RequestedRegion: Dimension: 2 Index: [0, 0] Size: [0, 0] 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 PixelContainer: ImportImageContainer (0x561bea401390) RTTI typeinfo: itk::ImportImageContainer<unsigned long, float> Reference Count: 1 Modified Time: 869 Debug: Off Object Name: Observers: none Pointer: 0 Container manages memory: true Size: 0 Capacity: 0
itk.Image.GetTypes()
<itkTemplate itk::Image> Options: [<itkCType bool>, 2] [<itkCType bool>, 3] [<itkCType bool>, 4] [<itkCType double>, 2] [<itkCType double>, 3] [<itkCType double>, 4] [<itkCType float>, 2] [<itkCType float>, 3] [<itkCType float>, 4] [<itkCType signed int>, 2] [<itkCType signed int>, 3] [<itkCType signed int>, 4] [<itkCType signed short>, 2] [<itkCType signed short>, 3] [<itkCType signed short>, 4] [<itkCType unsigned char>, 2] [<itkCType unsigned char>, 3] [<itkCType unsigned char>, 4] [<itkCType unsigned int>, 2] [<itkCType unsigned int>, 3] [<itkCType unsigned int>, 4] [<itkCType unsigned long long>, 2] [<itkCType unsigned long long>, 3] [<itkCType unsigned long long>, 4] [<itkCType unsigned long>, 2] [<itkCType unsigned long>, 3] [<itkCType unsigned long>, 4] [<itkCType unsigned short>, 2] [<itkCType unsigned short>, 3] [<itkCType unsigned short>, 4] [<class 'itk.itkCoocurrenceTextureFeaturesImageFilterPython.itkVectorF8'>, 2] [<class 'itk.itkCoocurrenceTextureFeaturesImageFilterPython.itkVectorF8'>, 3] [<class 'itk.itkCoocurrenceTextureFeaturesImageFilterPython.itkVectorF8'>, 4] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorD2'>, 2] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorD2'>, 3] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorD2'>, 4] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorD3'>, 2] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorD3'>, 3] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorD3'>, 4] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorD4'>, 2] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorD4'>, 3] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorD4'>, 4] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorF2'>, 2] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorF2'>, 3] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorF2'>, 4] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorF3'>, 2] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorF3'>, 3] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorF3'>, 4] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorF4'>, 2] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorF4'>, 3] [<class 'itk.itkCovariantVectorPython.itkCovariantVectorF4'>, 4] [<class 'itk.itkFixedArrayPython.itkFixedArrayD2'>, 2] [<class 'itk.itkFixedArrayPython.itkFixedArrayD3'>, 3] [<class 'itk.itkFixedArrayPython.itkFixedArrayD4'>, 4] [<class 'itk.itkFixedArrayPython.itkFixedArrayF2'>, 2] [<class 'itk.itkFixedArrayPython.itkFixedArrayF3'>, 3] [<class 'itk.itkFixedArrayPython.itkFixedArrayF4'>, 4] [<class 'itk.itkOffsetPython.itkOffset2'>, 2] [<class 'itk.itkOffsetPython.itkOffset3'>, 3] [<class 'itk.itkOffsetPython.itkOffset4'>, 4] [<class 'itk.itkRGBAPixelPython.itkRGBAPixelUC'>, 2] [<class 'itk.itkRGBAPixelPython.itkRGBAPixelUC'>, 3] [<class 'itk.itkRGBAPixelPython.itkRGBAPixelUC'>, 4] [<class 'itk.itkRGBPixelPython.itkRGBPixelUC'>, 2] [<class 'itk.itkRGBPixelPython.itkRGBPixelUC'>, 3] [<class 'itk.itkRGBPixelPython.itkRGBPixelUC'>, 4] [<class 'itk.itkRunLengthTextureFeaturesImageFilterPython.itkVectorF10'>, 2] [<class 'itk.itkRunLengthTextureFeaturesImageFilterPython.itkVectorF10'>, 3] [<class 'itk.itkRunLengthTextureFeaturesImageFilterPython.itkVectorF10'>, 4] [<class 'itk.itkSparseFieldFourthOrderLevelSetImageFilterPython.itkNormalBandNodeID2'>, 2] [<class 'itk.itkSparseFieldFourthOrderLevelSetImageFilterPython.itkNormalBandNodeID3'>, 3] [<class 'itk.itkSparseFieldFourthOrderLevelSetImageFilterPython.itkNormalBandNodeID4'>, 4] [<class 'itk.itkSparseFieldFourthOrderLevelSetImageFilterPython.itkNormalBandNodeIF2'>, 2] [<class 'itk.itkSparseFieldFourthOrderLevelSetImageFilterPython.itkNormalBandNodeIF3'>, 3] [<class 'itk.itkSparseFieldFourthOrderLevelSetImageFilterPython.itkNormalBandNodeIF4'>, 4] [<class 'itk.itkSymmetricSecondRankTensorPython.itkSymmetricSecondRankTensorD2'>, 2] [<class 'itk.itkSymmetricSecondRankTensorPython.itkSymmetricSecondRankTensorD3'>, 3] [<class 'itk.itkSymmetricSecondRankTensorPython.itkSymmetricSecondRankTensorD4'>, 4] [<class 'itk.itkSymmetricSecondRankTensorPython.itkSymmetricSecondRankTensorF2'>, 2] [<class 'itk.itkSymmetricSecondRankTensorPython.itkSymmetricSecondRankTensorF3'>, 3] [<class 'itk.itkSymmetricSecondRankTensorPython.itkSymmetricSecondRankTensorF4'>, 4] [<class 'itk.itkVectorPython.itkVectorD2'>, 2] [<class 'itk.itkVectorPython.itkVectorD2'>, 3] [<class 'itk.itkVectorPython.itkVectorD2'>, 4] [<class 'itk.itkVectorPython.itkVectorD2'>, 5] [<class 'itk.itkVectorPython.itkVectorD3'>, 2] [<class 'itk.itkVectorPython.itkVectorD3'>, 3] [<class 'itk.itkVectorPython.itkVectorD3'>, 4] [<class 'itk.itkVectorPython.itkVectorD3'>, 5] [<class 'itk.itkVectorPython.itkVectorD4'>, 2] [<class 'itk.itkVectorPython.itkVectorD4'>, 3] [<class 'itk.itkVectorPython.itkVectorD4'>, 4] [<class 'itk.itkVectorPython.itkVectorD4'>, 5] [<class 'itk.itkVectorPython.itkVectorF1'>, 2] [<class 'itk.itkVectorPython.itkVectorF1'>, 3] [<class 'itk.itkVectorPython.itkVectorF1'>, 4] [<class 'itk.itkVectorPython.itkVectorF2'>, 2] [<class 'itk.itkVectorPython.itkVectorF2'>, 3] [<class 'itk.itkVectorPython.itkVectorF2'>, 4] [<class 'itk.itkVectorPython.itkVectorF3'>, 2] [<class 'itk.itkVectorPython.itkVectorF3'>, 3] [<class 'itk.itkVectorPython.itkVectorF3'>, 4] [<class 'itk.itkVectorPython.itkVectorF4'>, 2] [<class 'itk.itkVectorPython.itkVectorF4'>, 3] [<class 'itk.itkVectorPython.itkVectorF4'>, 4] [<class 'itk.stdcomplexPython.stdcomplexD'>, 2] [<class 'itk.stdcomplexPython.stdcomplexD'>, 3] [<class 'itk.stdcomplexPython.stdcomplexD'>, 4] [<class 'itk.stdcomplexPython.stdcomplexF'>, 2] [<class 'itk.stdcomplexPython.stdcomplexF'>, 3] [<class 'itk.stdcomplexPython.stdcomplexF'>, 4]
MetaDataDictionary
d = itk.MetaDataDictionary()
d["new_key"] = 5
print(f"'new_key' value: {d['new_key']}")
'new_key' value: 5
list
or tuple
.image = ImageType.New()
help(image.SetOrigin)
Help on method itkImageBase2_SetOrigin: itkImageBase2_SetOrigin(...) method of itk.itkImagePython.itkImageF2 instance SetOrigin(self, _arg) Parameters ---------- _arg: itkPointD2 const SetOrigin(self, origin) Parameters ---------- origin: double const * SetOrigin(self, origin) Parameters ---------- origin: float const *
list
where an itk.Index
, itk.Point
, or itk.Vector
is requested.image.SetOrigin([2, 10])
print(f"Image origin: {str(image.GetOrigin())}")
print(f"Image origin: {str(list(image.GetOrigin()))}")
print(f"Image origin: {str(tuple(image.GetOrigin()))}")
Image origin: itkPointD2 ([2, 10]) Image origin: [2.0, 10.0] Image origin: (2.0, 10.0)
import sklearn
First, we load 10 2D-images of circles with different radii and center position to which noise has been added and their corresponding ground truth segmentations.
l_label = []
l_image = []
for i in range(0, 10):
image_name = "data/sklearn/im%d.nrrd" % i
image = itk.imread(image_name, itk.F)
array = itk.array_from_image(image)
l_image.append(array)
label_name = "data/sklearn/im%d_label.nrrd" % i
image = itk.imread(label_name, itk.UC)
array = itk.array_from_image(image)
l_label.append(array)
size = itk.size(image)
print(size)
plt.subplot(1, 2, 1)
plt.imshow(l_image[0])
plt.title("Image")
plt.subplot(1, 2, 2)
plt.imshow(l_label[0])
plt.title("Segmentation")
itkSize2 ([50, 50])
Text(0.5, 1.0, 'Segmentation')
The goal is to find the segmentation based on the input image.
We create arrays of data:
X0 = l_image[0].flatten()
X = X0
Y = l_label[0].flatten()
for i in range(1, 10):
X = np.concatenate((X, l_image[i].flatten()))
Y = np.concatenate((Y, l_label[i].flatten()))
from sklearn.naive_bayes import GaussianNB
clf = GaussianNB()
clf.fit(X.reshape(-1, 1), Y)
result = clf.predict(X0.reshape(-1, 1)).reshape(size[0], size[1])
plt.imshow(result)
<matplotlib.image.AxesImage at 0x7ff470cf9fd0>
To improve our segmentation, we filter the input image with a median image filter and add this information as a second sample vector.
ITK is often used to read, reformat, denoise, and augment medical imaging data to improve the effectiveness of medical imaging models.
l_median = []
for i in range(0, 10):
image_name = "data/sklearn/im%d.nrrd" % i
image = itk.imread(image_name, itk.F)
median = itk.median_image_filter(image, radius=3)
array = itk.array_from_image(median)
l_median.append(array)
plt.gray()
plt.imshow(l_median[0])
plt.title("Median Filtered Image")
Text(0.5, 1.0, 'Median Filtered Image')
M0 = l_median[0].flatten()
M = M0
X0 = np.concatenate((X0.reshape(-1, 1), M0.reshape(-1, 1)), axis=1)
for i in range(1, 10):
M = np.concatenate((M, l_median[i].flatten()))
X = np.concatenate((X.reshape(-1, 1), M.reshape(-1, 1)), axis=1)
clf.fit(X, Y)
result = clf.predict(X0).reshape(50, 50)
plt.imshow(result)
<matplotlib.image.AxesImage at 0x7ff470c164d0>
n4_bias_field_correction_image_filter
smoothing_recursive_gaussian_image_filter
binary_fillhole_image_filter
median_image_filter
image = itk.imread("data/CBCT-TextureInput.png", itk.ctype("float"))
filtered_image = itk.median_image_filter(image, radius=3)
view(filtered_image, ui_collapsed=True)
<itkwidgets.viewer.Viewer at 0x7ff483ab6310>
mean_image_filter
otsu_threshold_image_filter
Uncomment and change the radius of the filter and observe the result.
# median_filtered_image = itk.median_image_filter(image, radius = XX)
# view(median_filtered_image)
# %load solutions/2_Using_ITK_in_Python_real_world_filters_median.py
Uncomment and replace filter with mean_image_filter
# mean_filtered_image = itk.filter(image, radius = 5)
# view(mean_filtered_image)
# %load solutions/2_Using_ITK_in_Python_real_world_filters_mean.py
Uncomment and replace filter with otsu_threshold_image_filter
# otsu_filtered_image = itk.filter(image)
# view(otsu_filtered_image)
# %load solutions/2_Using_ITK_in_Python_real_world_filters_otsu.py
obj = itk.SmartPointerObjectType.New()
(use auto-completion to see if New()
method exists)obj = itk.SimpleObjectType()
New()
method:itk.Image
itk.MedianImageFilter
New()
method:itk.Index
itk.RGBPixel
PixelType = itk.ctype("float")
image = itk.imread("data/CBCT-TextureInput.png", PixelType)
ImageType = itk.Image[PixelType, 2]
median_filter = itk.MedianImageFilter[ImageType, ImageType].New()
median_filter.SetInput(image)
median_filter.SetRadius(4)
median_filter.Update()
view(median_filter.GetOutput(), ui_collapsed=True)
<itkwidgets.viewer.Viewer at 0x7ff4712cd250>
MeanImageFilter
OtsuThresholdImageFilter
Uncomment and change the radius of the filter and observe the result.
# median_filter = itk.MedianImageFilter[ImageType, ImageType].New()
# median_filter.SetInput(image)
# median_filter.SetRadius(XX)
# median_filter.Update()
# median_filtered_image = median_filter.GetOutput()
# view(median_filtered_image)
# %load solutions/2_Using_ITK_in_Python_real_world_filters_MedianFilter.py
Uncomment and edit to use MeanImageFilter
# mean_filter = itk.XX[ImageType, ImageType].New()
# mean_filter.SetInput(XX)
# mean_filter.SetRadius(XX)
# mean_filter.Update()
# mean_filtered_image = mean_filter.GetOutput()
# view(mean_filtered_image)
# %load solutions/2_Using_ITK_in_Python_real_world_filters_MeanFilter.py
Uncomment and replace filter with OtsuThresholdImageFilter
# InputImageType = itk.Image[itk.ctype('float'), 2]
# OutputImageType = itk.Image[itk.ctype('short'), 2]
# otsu_filter = itk.OtsuThresholdImageFilter[XX]
# XX
# %load solutions/2_Using_ITK_in_Python_real_world_filters_OtsuFilter.py
New()
method?Update()
with filters!ITK filters have compile-time performance optimized for a specific image types and dimensions.
When an attempt is made to use a filter with an image type that is not supported, a error will occur like:
KeyError: "itkTemplate : No template [<class 'itkImagePython.itkImageD2'>] for the itk::ImageFileReader class"
# image = itk.imread("data/BrainProtonDensitySlice.png", itk.D)
# print(image)
To find the supported types for a filter, call .GetTypes()
on the filter. itk.imread
wraps, the itk.ImageFileReader
filter.
itk.ImageFileReader.GetTypes()
<itkTemplate itk::ImageFileReader> Options: [<class 'itk.itkCoocurrenceTextureFeaturesImageFilterPython.itkImageVF82'>,] [<class 'itk.itkCoocurrenceTextureFeaturesImageFilterPython.itkImageVF83'>,] [<class 'itk.itkCoocurrenceTextureFeaturesImageFilterPython.itkImageVF84'>,] [<class 'itk.itkImagePython.itkImageCD2'>,] [<class 'itk.itkImagePython.itkImageCD3'>,] [<class 'itk.itkImagePython.itkImageCD4'>,] [<class 'itk.itkImagePython.itkImageCF2'>,] [<class 'itk.itkImagePython.itkImageCF3'>,] [<class 'itk.itkImagePython.itkImageCF4'>,] [<class 'itk.itkImagePython.itkImageCVF22'>,] [<class 'itk.itkImagePython.itkImageCVF23'>,] [<class 'itk.itkImagePython.itkImageCVF24'>,] [<class 'itk.itkImagePython.itkImageCVF32'>,] [<class 'itk.itkImagePython.itkImageCVF33'>,] [<class 'itk.itkImagePython.itkImageCVF34'>,] [<class 'itk.itkImagePython.itkImageCVF42'>,] [<class 'itk.itkImagePython.itkImageCVF43'>,] [<class 'itk.itkImagePython.itkImageCVF44'>,] [<class 'itk.itkImagePython.itkImageD2'>,] [<class 'itk.itkImagePython.itkImageD3'>,] [<class 'itk.itkImagePython.itkImageD4'>,] [<class 'itk.itkImagePython.itkImageF2'>,] [<class 'itk.itkImagePython.itkImageF3'>,] [<class 'itk.itkImagePython.itkImageF4'>,] [<class 'itk.itkImagePython.itkImageRGBAUC2'>,] [<class 'itk.itkImagePython.itkImageRGBAUC3'>,] [<class 'itk.itkImagePython.itkImageRGBAUC4'>,] [<class 'itk.itkImagePython.itkImageRGBUC2'>,] [<class 'itk.itkImagePython.itkImageRGBUC3'>,] [<class 'itk.itkImagePython.itkImageRGBUC4'>,] [<class 'itk.itkImagePython.itkImageSI2'>,] [<class 'itk.itkImagePython.itkImageSI3'>,] [<class 'itk.itkImagePython.itkImageSI4'>,] [<class 'itk.itkImagePython.itkImageSS2'>,] [<class 'itk.itkImagePython.itkImageSS3'>,] [<class 'itk.itkImagePython.itkImageSS4'>,] [<class 'itk.itkImagePython.itkImageUC2'>,] [<class 'itk.itkImagePython.itkImageUC3'>,] [<class 'itk.itkImagePython.itkImageUC4'>,] [<class 'itk.itkImagePython.itkImageUI2'>,] [<class 'itk.itkImagePython.itkImageUI3'>,] [<class 'itk.itkImagePython.itkImageUI4'>,] [<class 'itk.itkImagePython.itkImageULL2'>,] [<class 'itk.itkImagePython.itkImageULL3'>,] [<class 'itk.itkImagePython.itkImageULL4'>,] [<class 'itk.itkImagePython.itkImageUS2'>,] [<class 'itk.itkImagePython.itkImageUS3'>,] [<class 'itk.itkImagePython.itkImageUS4'>,] [<class 'itk.itkImagePython.itkImageVF22'>,] [<class 'itk.itkImagePython.itkImageVF23'>,] [<class 'itk.itkImagePython.itkImageVF24'>,] [<class 'itk.itkImagePython.itkImageVF32'>,] [<class 'itk.itkImagePython.itkImageVF33'>,] [<class 'itk.itkImagePython.itkImageVF34'>,] [<class 'itk.itkImagePython.itkImageVF42'>,] [<class 'itk.itkImagePython.itkImageVF43'>,] [<class 'itk.itkImagePython.itkImageVF44'>,] [<class 'itk.itkRunLengthTextureFeaturesImageFilterPython.itkImageVF102'>,] [<class 'itk.itkRunLengthTextureFeaturesImageFilterPython.itkImageVF103'>,] [<class 'itk.itkRunLengthTextureFeaturesImageFilterPython.itkImageVF104'>,] [<class 'itk.itkVectorImagePython.itkVectorImageD2'>,] [<class 'itk.itkVectorImagePython.itkVectorImageD3'>,] [<class 'itk.itkVectorImagePython.itkVectorImageD4'>,] [<class 'itk.itkVectorImagePython.itkVectorImageF2'>,] [<class 'itk.itkVectorImagePython.itkVectorImageF3'>,] [<class 'itk.itkVectorImagePython.itkVectorImageF4'>,] [<class 'itk.itkVectorImagePython.itkVectorImageSS2'>,] [<class 'itk.itkVectorImagePython.itkVectorImageSS3'>,] [<class 'itk.itkVectorImagePython.itkVectorImageSS4'>,] [<class 'itk.itkVectorImagePython.itkVectorImageUC2'>,] [<class 'itk.itkVectorImagePython.itkVectorImageUC3'>,] [<class 'itk.itkVectorImagePython.itkVectorImageUC4'>,] [<class 'itk.itkVectorImagePython.itkVectorImageUS2'>,] [<class 'itk.itkVectorImagePython.itkVectorImageUS3'>,] [<class 'itk.itkVectorImagePython.itkVectorImageUS4'>,]
One approach to handle this type of error is is to read the image into a supported pixel type:
image = itk.imread("data/KitwareITK.jpg", itk.F)
Another approach is to cast the image to a supported image type:
InputImageType = itk.Image[itk.F, 2]
OutputImageType = itk.Image[itk.UC, 2]
cast_filter = itk.CastImageFilter[InputImageType, OutputImageType].New(image)
cast_filter.Update()
itk.imread(file_name [, pixel_type])
itk.imwrite(image, file_name [, compression])
itk.array_from_image(image)
and itk.array_view_from_image(image)
itk.image_from_array(arr)
and itk.image_view_from_array(arr)
itk.size(image)
itk.spacing(image)
itk.origin(image)
itk.index(image)
itk.physical_size(image)
C++ | ITK Python | Numpy |
---|---|---|
float | itk.F | numpy.float32 |
double | itk.D | numpy.float64 |
unsigned char | itk.UC | numpy.uint8 |
bool | itk.B | bool |
The complete list of types can be found in the ITK Software Guide. Alternatively, such correspondence can be obtained by the following methods.
# names in C++ and ITK python
print(itk.F == itk.ctype("float")) # True
print(itk.B == itk.ctype("bool")) # True
True True
# print the numpy names of ITK python data types
print(itk.D.dtype) # <class 'numpy.float64'>
print(itk.UC.dtype) # <class 'numpy.uint8'>
print(itk.B.dtype) # <class 'bool'>
<class 'numpy.float64'> <class 'numpy.uint8'> <class 'numpy.bool_'>
Some ITK functions (e.g., imread()) will automatically detect the pixel type and dimensions of the image.
However, in certain cases, you want to choose the pixel type of the image that is read.
# Automatically detect
image = itk.imread("data/KitwareITK.jpg")
print(type(image)) # <class 'itkImagePython.itkImageRGBUC2'>
# specify pixel type
image = itk.imread("data/KitwareITK.jpg", itk.ctype("unsigned char"))
print(type(image)) # <class 'itkImagePython.itkImageUC2'>
<class 'itk.itkImagePython.itkImageRGBUC2'> <class 'itk.itkImagePython.itkImageUC2'>
See also: the ITK Python Quick Start Guide