How to actually to convert 3d numpy array of DICOM images into vtkImageData and vtkAlgorithmOutput?

As I’ve previously in other topic mentioned, I have a vtkResliceCursor, which uses vtkImageData and vtkAlgorithmOutput. Both were provided by vtkDICOMImageReader but it had few flaws. So I’ve decided to generate a 3d numpy array from DICOM images and pass it to vtk.

After generating numpy array (and filling it) with datasets

slice_thickness = datasets[0].SliceThickness
pixels_spacing_0, pixels_spacing_1 = datasets[0].PixelSpacing

ratio = (slice_thinkness/((pixels_spacing_0 + pixels_spacing_1)/2))
numpy_array = np.zeros((
            int(len(datasets) * ratio), 
            datasets[0].pixel_array.shape[0], 
            datasets[0].pixel_array.shape[1]
            ))

I am stumbling on generating vtkImageData with numpy_to_vtk function, because all info on different sites seems kinda different from each other (like reshape numpy array or don’t and etc, flatten or ravel).
I tried to follow one of these examples, but it works not as expected and maybe its because its now missing vtkAlgorigthmOutput which few classes requires

        shape = numpy_array.shape
        if len(shape) < 2:
            raise Exception('numpy array must have dimensionality of at least 2')

        h, w = shape[0], shape[1]
        c = 1
        if len(shape) == 3:
            c = shape[2]

        # Reshape 2D image to 1D array suitable for conversion to a
        # vtkArray with numpy_support.numpy_to_vtk()
        linear_array = np.reshape(numpy_array, (w*h, c))

        vtk_array = numpy_to_vtk(linear_array)

        self.image = vtkImageData()
        self.image.SetDimensions(w, h, 1)
        self.image.GetPointData().SetScalars(vtk_array)

So basically how to get vtkAlgorithmOutput so I can set classes with SetInputConnection(self.algorithm.GetOutputPort())?

Before getting to your question, note that vtk.util.numpy_support has been superseded by the vtk.numpy_interface that was developed for Paraview:

from vtk.numpy_interface import dataset_adapter

vtk_array = dataset_adapter.numpyTovtkDataArray(linear_array, "PixelData")

This interface requires you to provide a name for the VTK array, and 'PixelData' is a natural name for DICOM data. The older vtk.util.numpy_support is not scheduled for removal from VTK, but it is unlikely to receive any improvements or even basic maintenance in the future.


For the SetInputConnection() issue, you can use vtkTrivialProducer to bridge the gap:

self.image_producer = vtkTrivialProducer()
self.image_producer.SetOutput(self.image)

then

some_algorithm.SetInputConnection(self.image_producer.GetOutputPort())
1 Like

Follow-up: I was wrong about vtk.util.numpy_support, it looks like it is still being actively maintained, so there’s no reason not to continue using it. In fact, the vtk.numpy_interface module that I recommended is implemented via vtk.util.numpy_support.

However, it still is good practise to supply a name for any vtkDataArray that you create. These names are useful for debugging, and some filters and mappers allow selection of arrays by name. Naming an array is as simple as this:

vtk_array.SetName('PixelData')