I have been struggling with a bug (in my opinion) of GetImageFromArray in the Numpy bridge. In RTK, I need to graft an Image to a CudaImage when I want to use a Cuda filter using non-Cuda images. See, e.g., this example. However, I sometimes had weird memory behavior which I finally understood: when using GetImageFromArray, the management of the memory is left to numpy by backing up the array in _ndarr, see the code here. When grafting the image created by GetImageFromArray, _ndarr is not copied and the memory is freed if the original image is. Hence the issue. Here is a minimal example to reproduce the problem (hoping the memory is actually overwritten by np.zeros, it worked on my MacOS):
import itk import numpy as np img1 = np.ones(*3).astype(np.float32) img1 = itk.GetImageFromArray(img1) itk.ImageFileWriter(FileName='img1.mha', Input=img1) img2 = type(img1).New() img2.Graft(img1) del img1 np.zeros(*3).astype(np.float32) itk.ImageFileWriter(FileName='img2.mha', Input=img2)
Problem; img1 and img2 differ and they should not (with Cuda, cudaMemcpy using img2’s CPU memory pointer hangs…). I have simple workarounds (keep img1) but I think it’s a bug. I see two solutions:
- copy the member _ndarr when grafting (when it exists), but I don’t know how to do that with swig.
- don’t copy the numpy array but create a buffer, copy the data and let the buffer container handle its memory.
I’m happy to try the second solution (or another suggestion) if you agree. What do you think?