I'm discovering VTK and want to use it to plot a 3D numpy array. So far, I've managed to convert a numpy array to a vtk.Volume
and displaying it but from there I am having a hard time getting something pretty.
I get a very blocky rendering like this :
and I would like a smooth rendering, so I guess either this volume but smoothed, or the surface extracted from this volume smoothed.
I've tested a bunch of vtk mappers for this volume, like SmartVolumeMapper
, and played around with the Shader and the Interpolation, but did not get great results.
Here is my code (in Python) :
import vtk
import numpy as np
npa= #some 3D numpy array
[h,w,z]=npa.shape
#importing the numpy array (comes from http://www.vtk.org/Wiki/VTK/Examples/Python/vtkWithNumpy)
dataImporter = vtk.vtkImageImport()
data_string = npa.tostring()
dataImporter.CopyImportVoidPointer(data_string, len(data_string))
dataImporter.SetDataScalarTypeToUnsignedChar()
dataImporter.SetNumberOfScalarComponents(1)
dataImporter.SetDataExtent(0,z-1, 0, w-1, 0,h-1)
dataImporter.SetWholeExtent(0,z-1, 0,w-1, 0,h-1)
#Defining a transparency function
alphaChannelFunc = vtk.vtkPiecewiseFunction()
alphaChannelFunc.AddPoint(0, 0.0)
alphaChannelFunc.AddPoint(255, 1)
# Defining a color function
colorFunc = vtk.vtkColorTransferFunction()
colorFunc.AddRGBPoint(255, 1.0, 1.0, 1.0)
colorFunc.AddRGBPoint(128, 0.0, 0, 1.0)
#Creating the volume
volumeProperty = vtk.vtkVolumeProperty()
volumeProperty.SetColor(colorFunc)
volumeProperty.SetScalarOpacity(alphaChannelFunc)
volumeProperty.ShadeOn()
volumeProperty.SetInterpolationTypeToLinear()
#Creating the mapper
compositeFunction = vtk.vtkVolumeRayCastCompositeFunction()
volumeMapper = vtk.vtkVolumeRayCastMapper()
volumeMapper.SetVolumeRayCastFunction(compositeFunction)
volumeMapper.SetInputConnection(dataImporter.GetOutputPort())
#Creating the volume actor
volume = vtk.vtkVolume()
volume.SetMapper(volumeMapper)
volume.SetProperty(volumeProperty)
#Creating the renderer
renderer = vtk.vtkRenderer()
renderWin = vtk.vtkRenderWindow()
renderWin.AddRenderer(renderer)
renderInteractor = vtk.vtkRenderWindowInteractor()
renderInteractor.SetRenderWindow(renderWin)
#Adding the actor
renderer.AddVolume(volume)
renderer.SetBackground(0, 0, 0)
renderWin.SetSize(400, 400)
#Launching the renderer
renderInteractor.Initialize()
renderWin.Render()
renderInteractor.Start()
I get the impression that a Volume
actor is not the way to go to get something pretty, maybe I should go for a PolyData
or something ? I went through the Marching Cubes example (in C++) which seems to take a volume and extract a surface out of it, but I can't get it to work for the moment (no errors but output is a completely white buggy window which won't close).
I could dive more into it to try and get it to work but first I would like to get input from you guys, since I'm a beginner in VTK and maybe I'm handling this all wrong.
I'm using Python 2.7.12 and vtk 5.10.1 on Ubuntu 14.