[yt-users] VTK how to Import 3D image data via imageImport on c++ for Volume Rendering

Honghe 397667796 at qq.com
Wed Oct 12 19:46:04 PDT 2016


down votefavorite


Thanks for VTK first, it is a nice Tool. But I meet a problem as follow. 

Through VTK Python API, I can import/make 3d image data and Volume Rendering as follow:



And the Python code is:
# coding=utf-8 import vtk from numpy import * import random num = 74 # We begin by creating the data we want to render. # For this tutorial, we create a 3D-image containing three overlaping cubes. # This data can of course easily be replaced by data from a medical CT-scan or anything else three dimensional. # The only limit is that the data must be reduced to unsigned 8 bit or 16 bit integers. data_matrix = zeros([num, num, num], dtype=uint8) # data_matrix[0:35, 0:35, 0:35] = 50 # data_matrix[25:55, 25:55, 25:55] = 100 # data_matrix[45:74, 45:74, 45:74] = 150 for i in range(0, num - 1):     for j in range(0, num - 1):         for k in range(0, num - 1):             data_matrix[i:i + 1, j:j + 1, k:k + 1] = 100 # For VTK to be able to use the data, it must be stored as a VTK-image. This can be done by the vtkImageImport-class which # imports raw data and stores it. dataImporter = vtk.vtkImageImport() # The preaviusly created array is converted to a string of chars and imported. data_string = data_matrix.tostring() # dataImporter.CopyImportVoidPointer(data_string, len(data_string)) dataImporter.SetImportVoidPointer(data_matrix) # The type of the newly imported data is set to unsigned char (uint8) dataImporter.SetDataScalarTypeToUnsignedChar() # Because the data that is imported only contains an intensity value (it isnt RGB-coded or someting similar), the importer # must be told this is the case. dataImporter.SetNumberOfScalarComponents(1) # The following two functions describe how the data is stored and the dimensions of the array it is stored in. For this # simple case, all axes are of length 75 and begins with the first element. For other data, this is probably not the case. # I have to admit however, that I honestly dont know the difference between SetDataExtent() and SetWholeExtent() although # VTK complains if not both are used. dataImporter.SetDataExtent(0, 74, 0, 74, 0, 74) dataImporter.SetWholeExtent(0, 74, 0, 74, 0, 74) # The following class is used to store transparencyv-values for later retrival. In our case, we want the value 0 to be # completly opaque whereas the three different cubes are given different transperancy-values to show how it works. alphaChannelFunc = vtk.vtkPiecewiseFunction() alphaChannelFunc.AddPoint(0, 0.0) # alphaChannelFunc.AddPoint(50, 0.001) # alphaChannelFunc.AddPoint(100, 0.02) alphaChannelFunc.AddPoint(150, 0.02) # This class stores color data and can create color tables from a few color points. For this demo, we want the three cubes # to be of the colors red green and blue. colorFunc = vtk.vtkColorTransferFunction() colorFunc.AddRGBPoint(50, 0.0, 0.2, 0.2) colorFunc.AddRGBPoint(100, 0.0, 1.0, 0.0) colorFunc.AddRGBPoint(150, 0.0, 0.0, 1.0) # The preavius two classes stored properties. Because we want to apply these properties to the volume we want to render, # we have to store them in a class that stores volume prpoperties. volumeProperty = vtk.vtkVolumeProperty() volumeProperty.SetColor(colorFunc) volumeProperty.SetScalarOpacity(alphaChannelFunc) # This class describes how the volume is rendered (through ray tracing). compositeFunction = vtk.vtkVolumeRayCastCompositeFunction() # We can finally create our volume. We also have to specify the data for it, as well as how the data will be rendered. volumeMapper = vtk.vtkVolumeRayCastMapper() volumeMapper.SetVolumeRayCastFunction(compositeFunction) volumeMapper.SetInputConnection(dataImporter.GetOutputPort()) # The class vtkVolume is used to pair the preaviusly declared volume as well as the properties to be used when rendering that volume. volume = vtk.vtkVolume() volume.SetMapper(volumeMapper) volume.SetProperty(volumeProperty) # With almost everything else ready, its time to initialize the renderer and window, as well as creating a method for exiting the application renderer = vtk.vtkRenderer() renderWin = vtk.vtkRenderWindow() renderWin.AddRenderer(renderer) renderInteractor = vtk.vtkRenderWindowInteractor() renderInteractor.SetRenderWindow(renderWin) # We add the volume to the renderer ... renderer.AddVolume(volume) # ... set background color to white ... renderer.SetBackground(1, 1, 1) # ... and set window size. renderWin.SetSize(400, 400) # A simple function to be called when the user decides to quit the application. def exitCheck(obj, event):     if obj.GetEventPending() != 0:         obj.SetAbortRender(1) # Tell the application to use the function as an exit check. # renderWin.AddObserver("AbortCheckEvent", exitCheck) renderInteractor.Initialize() # Because nothing will be rendered without any input, we order the first render manually before control is handed over to the main-loop. renderWin.Render() renderInteractor.Start()
But for c++ API, I can not get the same Volume Rendering through ImageImport.

The following code is the C++ code I write refer to the above Python code. But the result is as follow:



the C++ code I write refer to the above Python code:
#include <iostream> #include <vtkStructuredPointsReader.h> #include <vtkVolumeRayCastCompositeFunction.h> #include <vtkVolumeRayCastMapper.h> #include <vtkRendererCollection.h> #include <vtkSmartPointer.h> #include <vtkImageImport.h> #include <stdlib.h> // VTK includes #include "vtkBoxWidget.h" #include "vtkCamera.h" #include "vtkCommand.h" #include "vtkColorTransferFunction.h" #include "vtkDICOMImageReader.h" #include "vtkImageData.h" #include "vtkImageResample.h" #include "vtkMetaImageReader.h" #include "vtkPiecewiseFunction.h" #include "vtkPlanes.h" #include "vtkProperty.h" #include "vtkRenderer.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkVolume.h" #include "vtkVolumeProperty.h" #include "vtkXMLImageDataReader.h" #include "vtkFixedPointVolumeRayCastMapper.h" int main() {     std::cout << "Hello, World!" << std::endl;     // create data     // Create a c-style image     const int width = 4;     const int height = 4;     const int depth = 4;     unsigned char cImage[width * height * depth];     unsigned char value = 0;     for (unsigned int row = 0; row < height; ++row) {         for (unsigned int col = 0; col < width; ++col) {             for (unsigned int z = 0; z < depth; ++z) {                 cImage[row * width * depth + col * depth + z] = 100;             }         }     }     // Convert the c-style image to a vtkImageData     vtkSmartPointer<vtkImageImport> imageImport =             vtkSmartPointer<vtkImageImport>::New();     imageImport->SetImportVoidPointer(cImage);     imageImport->SetDataScalarTypeToUnsignedChar();     imageImport->SetNumberOfScalarComponents(1);     imageImport->SetDataSpacing(1, 1, 1);     imageImport->SetDataOrigin(0, 0, 0);     imageImport->SetDataExtent(0, width - 1, 0, height - 1, 0, depth - 1);     imageImport->SetWholeExtent(0, width - 1, 0, height - 1, 0, depth - 1); //    imageImport->SetDataExtentToWholeExtent(); //    imageImport->SetDataScalarTypeToUnsignedChar(); //    imageImport->SetNumberOfScalarComponents(1);     imageImport->Update();     // Create the standard ren, render window and interactor     vtkRenderer *ren = vtkRenderer::New();     vtkRenderWindow *renWin = vtkRenderWindow::New();     renWin->AddRenderer(ren);     vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();     iren->SetRenderWindow(renWin);     // Create the reader for the data //    vtkStructuredPointsReader *reader = vtkStructuredPointsReader::New(); //    reader->SetFileName("/home/honhe/ClionProjects/Demo_vtk_SimpleRayCast/ironProt.vtk");     // Create transfer mapping scalar value to opacity     vtkPiecewiseFunction *opacityTransferFunction = vtkPiecewiseFunction::New();     opacityTransferFunction->AddPoint(0, 0.0);     opacityTransferFunction->AddPoint(150, 0.2);     // Create transfer mapping scalar value to color     vtkColorTransferFunction *colorTransferFunction = vtkColorTransferFunction::New();     colorTransferFunction->AddRGBPoint(0.0, 0.0, 0.0, 0.0);     colorTransferFunction->AddRGBPoint(100.0, 0.0, 1.0, 0.0);     // The property describes how the data will look     vtkVolumeProperty *volumeProperty = vtkVolumeProperty::New();     volumeProperty->SetColor(colorTransferFunction);     volumeProperty->SetScalarOpacity(opacityTransferFunction);     volumeProperty->ShadeOn();     volumeProperty->SetInterpolationTypeToLinear();     // The mapper / ray cast function know how to render the data     vtkVolumeRayCastCompositeFunction *compositeFunction = vtkVolumeRayCastCompositeFunction::New();     vtkVolumeRayCastMapper *volumeMapper = vtkVolumeRayCastMapper::New();     volumeMapper->SetVolumeRayCastFunction(compositeFunction);     volumeMapper->SetInputConnection(imageImport->GetOutputPort());     // The volume holds the mapper and the property and     // can be used to position/orient the volume     vtkVolume *volume = vtkVolume::New();     volume->SetMapper(volumeMapper);     volume->SetProperty(volumeProperty);     ren->AddVolume(volume);     ren->SetBackground(1, 1, 1);     renWin->SetSize(400, 400);     iren->Initialize();     renWin->Render();     iren->Start();     return 0; }
And I search example code, but only find the following, they can not work with 3d image data.

This example show how to import 2d Image VTK/Examples/Cxx/Images/ImageImport

And this example show how to deal with 3d image, but the API is out of date This example demonstrates how to set and access locations in a 3D image.

This problem also post in http://stackoverflow.com/questions/39976669/vtk-how-to-import-3d-image-data-via-imageimport-on-c, but no responce right now.

Any help appreciate!




------------------
Honghe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.spacepope.org/pipermail/yt-users-spacepope.org/attachments/20161013/2a998455/attachment-0001.htm>


More information about the yt-users mailing list