Feature Request: Make empty `itk.Image` and related data serializable (pickleable) for use with `dask.distributed`
Description
ITK supports Python's pickle serialization technique for fully buffered itk.Image objects (see https://github.com/InsightSoftwareConsortium/ITK/pull/2829), but not for advanced use cases of itk.Image.
It would be good to support the following cases:
- Unbuffered
itk.Imagedescribing a relationship between an oriented spatial bounding box and an implied underlying voxel array. I.e.,image.GetBufferedRegion()is zero andimage.GetLargestPossibleRegion()is greater than zero. - Partially buffered
itk.Imagedescribing a subimage. I.e.,image.GetBufferedRegion()is greater than zero and is strictly less thanimage.GetLargestPossibleRegion(). - Directly support serialization of related
itk.Imageheader objects such asitk.ImageRegionanditk.Matrix.
Steps to Reproduce
For case 1:
import itk
import pickle
reader = itk.ImageFileReader[itk.Image[itk.F,3]].New()
reader.SetFileName('path/to/image.mha')
reader.UpdateOutputInformation() # update without buffering
result = pickle.dumps(reader.GetOutput())
Expected behavior
Image is serialized to a bytestring and can be deserialized with pickle.loads(result) with no loss of information
Actual behavior
Serialization fails because there is not a voxel buffer to convert to NumPy:
>>> pickle.dumps(im2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\venvs\venv-itk\lib\site-packages\itk\itkImagePython.py", line 7297, in __getstate__
state = itk.dict_from_image(self)
File "C:\venvs\venv-itk\lib\site-packages\itk\support\extras.py", line 791, in dict_from_image
pixel_arr = itk.array_from_image(image)
File "C:\venvs\venv-itk\lib\site-packages\itk\support\extras.py", line 335, in GetArrayFromImage
return _GetArrayFromImage(
File "C:\venvs\venv-itk\lib\site-packages\itk\support\extras.py", line 317, in _GetArrayFromImage
return templatedFunction(img, keep_axes, update)
File "C:\venvs\venv-itk\lib\site-packages\itk\itkPyBufferPython.py", line 3839, in GetArrayFromImage
arrayView = itkPyBufferIF3.GetArrayViewFromImage(image, keep_axes, update)
File "C:\venvs\venv-itk\lib\site-packages\itk\itkPyBufferPython.py", line 3820, in GetArrayViewFromImage
memview = itkPyBufferIF3._GetArrayViewFromImage(image)
ValueError: PyMemoryView_FromBuffer(): info->buf must not be NULL
Additional Information
Related to work with dask.distributed in https://github.com/InsightSoftwareConsortium/itk-dreg
cc @thewtex
arrayView = itkPyBufferIF3.GetArrayViewFromImage(image, keep_axes, update)
At this point, if the image buffer is empty / has not been allocated, we should return None.
Partially buffered itk.Image describing a subimage. I.e., image.GetBufferedRegion() is greater than zero and is strictly less than image.GetLargestPossibleRegion()
I will work on this in coordination with https://github.com/InsightSoftwareConsortium/itk-wasm/issues/983.
Directly support serialization of related itk.Image header objects such as itk.ImageRegion and itk.Matrix.
I think Direction (Matrix) is already serialized.
I think Direction (Matrix) is already serialized.
I see the following behavior in itk==v5.4rc1:
>>> pickle.dumps(itk.Matrix[itk.D,3,3]())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot pickle 'SwigPyObject' object
Ah, yes, it currently has to be explicitly converted to a NumPy array.