vtkVolume can color mapping?

now i making pI’m creating a program that overlays two objects and prints one object with color mapping based on the coordinate values.
The overlay output was successful, but I could not find a way to do color mapping.
I output two objects using vtkVolume. However, the problem is that I can not extract the value corresponding to the coordinates of the object to be color-mapped in vtkVolume. How do I do color mapping to a volume? Thank you very much for your answers.

    import vtk    
    import nrrd    
    import numpy as np    
    from vtk.util import numpy_support as VN

    renWin = vtk.vtkRenderWindow()
    renderer = vtk.vtkRenderer()
    renWin.AddRenderer(renderer)
    iren = vtk.vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)
    lstVolume = []

    reader = vtk.vtkNrrdReader()
    reader.SetFileName('sample_nrrd.nrrd')
    reader.Update()

    vol = ImageDataToVolume(reader.GetOutput())
    lstVolume.append(vol)
    renderer.AddVolume(vol)

    reader1 = vtk.vtkNrrdReader()
    reader1.SetFileName('Segmentation-label_2.nrrd')
    reader1.Update()

    scalar = GetScalarData(reader1)
    print(scalar)
    vol1 = ImageDataToVolume(reader1.GetOutput())
    lstVolume.append(vol1)
    renderer.AddVolume(vol1)

    iren.Initialize()
    renWin.Render()
    iren.Start()
def ImageDataToVolume(imagedata):


    mapper = vtk.vtkSmartVolumeMapper()
    mapper.SetInputData(imagedata)

    vol = vtk.vtkVolume()
    vol.SetMapper(mapper)

    ApplyAutoVolumeProperty(imagedata, mapper, vol)

    return vol
def GetScalarData(ptData):

    vtkDataArray = ptData.GetScalars()
    if vtkDataArray == None:
        return np.array([])
    sData = VN.vtk_to_numpy(vtkDataArray)
    return sData

def ApplyAutoVolumeProperty(pData, pMapper, pVolume):


    scalar = GetScalarData(pData.GetPointData())

    min_value = -1000
    max_value = 3095

    fCenter = (max_value - min_value) / 2.0
    fWidth = max_value - min_value

    fLow = fCenter - fWidth / 2.0
    fHigh = fCenter + fWidth / 2.0

    fTerm = fHigh - fLow;

    print("min, max : " + str(min_value) + ", " + str(max_value))

    pMapper.SetBlendModeToComposite()

    volProperty = vtk.vtkVolumeProperty()
    volProperty.ShadeOn()
    volProperty.SetInterpolationTypeToLinear()
    volProperty.SetDiffuse(0.7)
    volProperty.SetAmbient(0.2)
    volProperty.SetSpecular(0.3)
    volProperty.SetSpecularPower(30.0)

    otf = vtk.vtkPiecewiseFunction()
    otf.AddPoint(fLow, 0.0) # start
    otf.AddPoint(fHigh, 1.0) # end
    volProperty.SetScalarOpacity(0, otf)

    ctf = vtk.vtkColorTransferFunction()
    ctf.AddRGBPoint(fLow + fTerm * 0 * 0.2, 0.0, 0.0, 0.0)
    ctf.AddRGBPoint(fLow + fTerm * 1 * 0.2, 0.7, 0.4, 0.1)
    ctf.AddRGBPoint(fLow + fTerm * 2 * 0.2, 0.6, 0.5, 0.3)
    ctf.AddRGBPoint(fHigh, 1.0, 1.0, 1.0)
    volProperty.SetColor(0, ctf)

    pVolume.SetProperty(volProperty)
    pass
if __name__ == '__main__':
    main()

Consider using the vtkplotter helper module, which greatly simplifies it ito:

from vtkplotter import datadir, load, show

# note that vol1 is a vtkVolume:
vol1 = load(datadir+'vase.vti').mode(0) # can read .nrrd
vol1.alpha([0,0,0,0.5,0.5,0.6])  # opacity transfer func on the scalar range
vol1.color(['red','g', (1,0,1)]) # color transfer func

vol2 = load(datadir+'vase.vti').mode(1).addPos(60,0,0)
vol2.alpha([0,0,1,1])
vol2.color(['r','g', (0,0,1)])

show(vol1, vol2, bg='white', axes=True)

Screenshot%20from%202019-06-25%2021-25-25

check out e.g. this for a longer explanation.

1 Like

Thanks for reply!
I want to ask something. I want to do color mapping based on the coordinate values in the nrrd file. Can vtkplotter use such features?
And How Can i print original object colors

it is not very clear to me what are you really trying to visualize… maybe you wish to isosurface your volume, and only then color the resulting mesh based on its coordinates… (?)

1 Like

image

I currently use two nrrd files as shown.
The object on the right outputs the original color value, but the object on the left does not output the original color.
I did not set the color value separately and only adjusted Opacity.

from dot import *
import vtk
import dot
from vtkplotter import *
def main():
vol1 = load(‘Segmentation-label_2.nrrd’).mode(1).addPos(60,0,0)

vol1.alpha([0, 1, 1, 1, 1])  # opacity transfer func on the scalar range



vol2 = load('sample_nrrd.nrrd').mode(0)
vol2.alpha([0,0,0,0.4,0])   # opacity transfer func on the scalar range


show(vol1,vol2, bg='white',axes=True)

if name == ‘main’:
main()

I may be missing something but the expression “original color” has no meaning: there is no original color. There is a scalar associated to the volume and you can use this scalar to colorize the volume the way you like…
I’m afraid I cannot help you without having access to the data.

1 Like

I understand your words. Finally, I want to ask. Is it possible to access the values of each voxel instead of changing the entire color of one object, and simply change the color?

Hi,yes …but this is what vol1.color([...]) is already doing: you assign a specific color that you choose to a specific range that you choose of the scalar.
E.g. say that your voxel scalar runs from -3 to 6 and you want -3 to show red and 1.5 violet and 6 green, then just set:
vol1.color(['red', 'violet', 'green'])

You can also print the histogram of your scalar with
vol1.printHistogram(logscale=True), e.g.
image

1 Like

Thank you very much. Your kind reply was helpful!

1 Like