2016-10-11 3 views
0

ボリュームレンダリングのためのC++にimageImportを経由して、3D画像データをインポートする方法を、私たちは次のように3D画像データとボリュームレンダリングを作る/インポートすることができます。VTK VTKのPython APIを通じて

enter image description here

とPythonコードされます:

# 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 overlapping 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 previously 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 isn't RGB-coded or something 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 don't 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 transparency-values for later retrieval. In our case, we want the value 0 to be 
# completely opaque whereas the three different cubes are given different transparency-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 previous 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 properties. 
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 previously 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() 

しかし、C++ APIでは、ImageImportで同じボリュームレンダリングを取得できません。

次のコードは、上記のPythonコードを参照して作成したC++コードです。 は、しかし、その結果は以下の通りです:

enter image description here

私は上記のPythonコードを参照して書き込みをC++コード:

#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; 
} 

そして、私はサンプルコードを検索するが、唯一以下のことを、彼らはできます3D画像データでは動作しません。

  • この例では、2D画像
  • VTK/Examples/Cxx/Images/ImageImportをインポートする方法を示し、この例では、3D画像に対処する方法を示しているが、APIは、すべてのヘルプは感謝

This example demonstrates how to set and access locations in a 3D image. の外にあります!

答えて

0

あなたのプログラムに感謝します。 あなたのプログラムを使って同じ結果が得られました。その理由は、選択されたレイキャスト関数---コンポジット関数です。

//The mapper/ray cast fuction know how to render the data 
// vtkSmartPointer<vtkVolumeRayCastCompositeFunction> compositeFunc 
//   = vtkSmartPointer<vtkVolumeRayCastCompositeFunction>::New(); 
    vtkSmartPointer<vtkVolumeRayCastMIPFunction> compositeFunc 
      = vtkSmartPointer<vtkVolumeRayCastMIPFunction>::New(); 
    vtkSmartPointer<vtkVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkVolumeRayCastMapper>::New(); 

私は非常によく2つの機能を理解することはできません。 は、私はこのように、MIP機能には、この機能を変更し、うまく。 VTKTextbookではよく説明されています。

+0

既に回答が見つかった場合は、私に答えを教えていただければ幸いです。大いに感謝する。私はvtkの方が新しく、他の人と話すことができてうれしいです。 (私は中国人で、私の英語はうまくいきません、ありがとう)。 – MySuperPower

関連する問題