I have a 3D numpy array and I am trying to volume render it using VTK. However, I get a completely different volume rendering when I visualise it. I suspect it has something to do with my conversion of numpy array to the VTK image format but I can't seem to figure out where I am going wrong. I have uploaded the numpy array here .
Can someone help me figure out where I'm going wrong?
This is my code:
#!/usr/bin/env python
import os
import numpy as np
# noinspection PyUnresolvedReferences
import vtkmodules.vtkInteractionStyle
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkIOImage import vtkImageImport
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonCore import (
VTK_VERSION_NUMBER,
vtkVersion
)
from vtkmodules.vtkCommonDataModel import vtkImageData
from vtkmodules.vtkFiltersCore import (
vtkFlyingEdges3D,
vtkMarchingCubes
)
from vtkmodules.vtkFiltersSources import vtkSphereSource
from vtkmodules.vtkIOImage import vtkDICOMImageReader
from vtkmodules.vtkImagingHybrid import vtkVoxelModeller
from vtkmodules.vtkRenderingCore import (
vtkActor,
vtkPolyDataMapper,
vtkRenderWindow,
vtkRenderWindowInteractor,
vtkRenderer
)
ArrayDicom = np.load('test3.npy')
data_matrix = ArrayDicom
w, d, h = ArrayDicom.shape
colors = vtkNamedColors()
iso_value = 200
reader = vtkImageImport()
data_string = data_matrix.tobytes()
reader.CopyImportVoidPointer(data_string, len(data_string))
reader.SetDataScalarTypeToUnsignedChar()
reader.SetNumberOfScalarComponents(1)
reader.SetDataExtent(0, w-1, 0, d-1, 0, h-1)
reader.SetWholeExtent(0, w-1, 0, d-1, 0, h-1)
reader.Update()
volume = vtkImageData()
volume.DeepCopy(reader.GetOutput())
surface = vtkMarchingCubes()
surface.SetInputData(volume)
surface.ComputeNormalsOn()
surface.SetValue(0, iso_value)
renderer = vtkRenderer()
renderer.SetBackground(colors.GetColor3d('DarkSlateGray'))
render_window = vtkRenderWindow()
render_window.AddRenderer(renderer)
render_window.SetWindowName('MarchingCubes')
interactor = vtkRenderWindowInteractor()
interactor.SetRenderWindow(render_window)
mapper = vtkPolyDataMapper()
mapper.SetInputConnection(surface.GetOutputPort())
mapper.ScalarVisibilityOff()
actor = vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(colors.GetColor3d('MistyRose'))
renderer.AddActor(actor)
render_window.Render()
interactor.Start()
This is my volume rendering:
This is my expected volume rendering:
Edit: My array is originally from a DICOM file but I get an error when I try to read it using VTK which is why I'm reading it using pydicom
into a numpy array and then converting it to a VTK Image object. Could it be that I lose some spacing information when I do this? Any help would be appreciated.
Numpy uses a different array ordering than VTK. You should be able to re-order w, h and d to get the right thing.
This is how you want it:
h, d, w = ArrayDicom.shape
OK, here's a conversion script that I used to convert to a VTK file:
import numpy as np
import SimpleITK as sitk
x = np.load("test3.npy")
y = sitk.GetImageFromArray(x)
sitk.WriteImage(y, "test3.vtk")
It's not as nice as correctly getting the VTK image import to work, but, well, I'm a SimpleITK guy, and I know that converting numpy works in SimpleITK.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.