I just want to be able to use a numpy array as itk.itkImagePython.itkImageF3
to feed it into a registration (without SimpleITK). Thanks!
Description of the issue with MWE
I get an error when trying to run any of these
import itk
import numpy as np
series_length = 4
holder = np.zeros((series_length, 10, 10, 3), dtype=np.uint8)
PixelType = itk.ctype("float")
Dimension = 3
ImageType = itk.Image[PixelType, Dimension]
# Option 1
itk_image = itk.image_from_array(holder[0], ttype=(ImageType,))
# Option 2
itk_image = itk.PyBuffer[ImageType].GetImageFromArray(holder[0])
Expected behaviour
Take a Numpy array into an ITK object which I can use for registration.
Actual result
RuntimeError: Size mismatch of image and Buffer.
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<string>", line 17, in __PYTHON_EL_eval
File "<string>", line 1, in <module>
File "/usr/lib/python3.10/itk/support/extras.py", line 394, in GetImageFromArray
return _GetImageFromArray(arr, "GetImageFromArray", is_vector, ttype)
File "/usr/lib/python3.10/itk/support/extras.py", line 386, in _GetImageFromArray
return templatedFunction(arr, is_vector)
File "/usr/lib/python3.10/itk/itkPyBufferPython.py", line 2592, in GetImageFromArray
imageView = itkPyBufferIF3.GetImageViewFromArray(ndarr, is_vector)
File "/usr/lib/python3.10/itk/itkPyBufferPython.py", line 2562, in GetImageViewFromArray
imgview = itkPyBufferIF3._GetImageViewFromArray(ndarr, ndarr.shape[::-1], 1)
SystemError: <built-in function itkPyBufferIF3__GetImageViewFromArray> returned a result with an exception set
Optional context
Current approach
The goal is to run a registration between two 3D objects as shown here. There, @dzenanz set the image type into itk.ImageRegistrationMethodv4
. The original data was created with
-
a numpy array
-
saved to a file and
-
read back with ~itk.imread
holder = np.zeros((series_length, *obj3d.shape), dtype=np.uint8)
fixed_image = itk.image_from_array(holder[0])
moving_image = itk.image_from_array(holder[-1])itk.imwrite(itk.image_from_array(holder[0]),
āitk_hello_registration.in1.vtkā)
itk.imwrite(itk.image_from_array(holder[-1]),
āitk_hello_registration.in4.vtkā)
fixedImageFile = āitk_hello_registration.in1.vtkā
movingImageFile = āitk_hello_registration.in4.vtkāPixelType = itk.ctype(āfloatā)
fixed_image = itk.imread(fixedImageFile, PixelType)
moving_image = itk.imread(movingImageFile, PixelType)
Related posts
Here, I have seen that a PyBuffer
can be used to specify the type of data for GetImageFromArray
(which is the same as image_from_array
).
ImageType = itk.Image[itk.RGBPixel[itk.UC], 3]
itk_image = itk.PyBuffer[ImageType].GetImageFromArray(np_image)
Also, here, I found that image types can be casted
PixelType = itk.ctype(āunsigned charā)
image = itk.imread("input_filename.png", PixelType)
dimension = image.GetImageDimension()
InputImageType = type(image)
OutputPixelType = itk.ctype(āfloatā)
OutputImageType = itk.Image[OutputPixelType, dimension]
cast = itk.CastImageFilter[InputImageType, OutputImageType].New(image)
itk.imwrite(cast, "output_filename.png")
Workaround
I have found that I can do this
fixed_image = itk.image_from_array(holder[0])
moving_image = itk.image_from_array(holder[-1])
# Set the data in the right format (casting)
fixed_castImageFilter = itk.CastImageFilter[
type(fixed_image), ImageType].New()
fixed_castImageFilter.SetInput(fixed_image)
moving_castImageFilter = itk.CastImageFilter[
type(moving_image), ImageType].New()
moving_castImageFilter.SetInput(moving_image)
followed by this
registration = itk.ImageRegistrationMethodv4[FixedImageType,MovingImageType].New(
FixedImage=fixed_castImageFilter,
MovingImage=moving_castImageFilter,
Metric=metric,
Optimizer=optimizer,
InitialTransform=initialTransform)
System
Table 1: Python and ITK versionsPython | 3.10.1 |
ITK | 5.2.1 |
Numpy | 1.21.5 |
Scipy | 1.7.3 |
Parabola_(GNU/Linux) | 5.15.12-gnu-1 |
gcc | 11.1.0 |