2017-07-28 3 views
3

J'utilise vtk library avec C++ pour générer et visualiser des données de voxels synthétiques avec un mappage de couleur et de transparence donné. Un exemple est montré ci-dessous: Sample ImageVisualisation de volume VTK Problème

Comme le montre la figure, les données sont en général en 3D, et cela fonctionne très bien. Cependant, dans des cas spécifiques lorsque les données deviennent 2D, les fenêtres de visualisation ne montrent rien.

Je poste quelques lignes de mon code qui peut être utile.

imageData = vtkSmartPointer<vtkImageData>::New(); 
imageData->SetDimensions(X1, X2, X3); //For 2D, one of X1,X2 & X3=1 
imageData->AllocateScalars(VTK_INT, 1); 
int* I = new int[X1X2X3](); //int X1X2X3 = X1*X2*X3 
I = static_cast<int*>(imageData->GetScalarPointer()); 

Veuillez noter que pour 2D, soit X1 = 1 ou X2 = 1 ou X3 = 1. Des suggestions?

EDIT: J'ajoute un code équivalent, qui démontrera exactement le problème que je suis face:

main.cpp

//#include <vtkAutoInit.h> // if not using CMake to compile, necessary to use this macro 
//#define vtkRenderingCore_AUTOINIT 3(vtkInteractionStyle, vtkRenderingFreeType, vtkRenderingOpenGL2) 
//#define vtkRenderingVolume_AUTOINIT 1(vtkRenderingVolumeOpenGL2) 
//#define vtkRenderingContext2D_AUTOINIT 1(vtkRenderingContextOpenGL2) 
#include <vtkSmartPointer.h> 
#include <vtkActor.h> 
#include <vtkRenderWindow.h> 
#include <vtkRenderer.h> 
#include <vtkRenderWindowInteractor.h> 
#include <vtkSmartVolumeMapper.h> 
#include <vtkColorTransferFunction.h> 
#include <vtkVolumeProperty.h> 
#include <vtkSampleFunction.h> 
#include <vtkPiecewiseFunction.h> 
#include <vtkImageData.h> 
#include <stdlib.h> 
using namespace std; 

int main() 
{ 
    //Declaring Variables 
    vtkSmartPointer<vtkImageData> imageData; 
    vtkSmartPointer<vtkVolumeProperty> volumeProperty; 
    vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity; 
    vtkSmartPointer<vtkColorTransferFunction> color; 
    vtkSmartPointer<vtkVolume> volume; 
    vtkSmartPointer<vtkSmartVolumeMapper> mapper; 
    vtkSmartPointer<vtkActor> actor; 
    vtkSmartPointer<vtkRenderer> renderer; 
    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor; 
    vtkSmartPointer<vtkRenderWindow> renderWindow; 
    int* I; 
    int X1, X2, X3, X1X2X3; 

    //Assigning Values , Allocating Memory 
    X1 = 10; 
    X2 = 10; 
    X3 = 10; 
    X1X2X3 = X1*X2*X3; 
    I = new int[X1X2X3](); 
    imageData = vtkSmartPointer<vtkImageData>::New(); 
    volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New(); 
    compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New(); 
    color = vtkSmartPointer<vtkColorTransferFunction>::New(); 
    volume = vtkSmartPointer<vtkVolume>::New(); 
    mapper = vtkSmartPointer<vtkSmartVolumeMapper>::New(); 
    actor = vtkSmartPointer<vtkActor>::New(); 
    renderer = vtkSmartPointer<vtkRenderer>::New(); 
    renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); 
    renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); 
    volumeProperty->ShadeOff(); 
    volumeProperty->SetInterpolationType(0); 
    volumeProperty->SetColor(color); 
    volumeProperty->SetScalarOpacity(compositeOpacity); 
    imageData->SetDimensions(X1, X2, X3); 
    imageData->AllocateScalars(VTK_INT, 1); 
    I = static_cast<int*>(imageData->GetScalarPointer()); 
    renderWindow->AddRenderer(renderer); 
    renderWindowInteractor->SetRenderWindow(renderWindow); 
    renderer->SetBackground(0.5, 0.5, 0.5); 
    renderWindow->SetSize(800, 800);  
    mapper->SetBlendModeToComposite(); 
    imageData->UpdateCellGhostArrayCache(); 
    mapper->SetRequestedRenderModeToRayCast(); 
    mapper->SetInputData(imageData); 
    volume->SetMapper(mapper); 
    volume->SetProperty(volumeProperty); 
    renderer->AddViewProp(volume); 
    volumeProperty->ShadeOff(); 

    //Setting Voxel Data and Its Properties 
    for (int i = 0; i < X1X2X3; i++) 
    { 
     I[i] = i; 
     compositeOpacity->AddPoint(i, 1); 
     color->AddRGBPoint(i, double(rand())/RAND_MAX, double(rand())/RAND_MAX, double(rand())/RAND_MAX); 
    } 

    renderer->ResetCamera(); 
    renderWindow->Render(); 
    renderWindowInteractor->Start(); 
    getchar(); 
    return 0; 
} 

CMakeLists.txt

cmake_minimum_required(VERSION 3.0) 
project(EvoSim) 
set(CMAKE_CXX_STANDARD 14) 
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) 
set(CMAKE_USE_RELATIVE_PATHS ON) 
#GRABBING VTK 
find_package(VTK REQUIRED) 
include(${VTK_USE_FILE}) 

add_executable(MAIN main.cpp) 
target_link_libraries(MAIN ${VTK_LIBRARIES}) 

Ceci conduit à une sortie comme ci-dessous (pour, X1 = X2 = X3 = 10) enter image description here

Cependant, si je fais X1 = 1, la fenêtre de sortie est vide.

EDIT:

Je viens de remarquer que le nombre de voxels le long d'une certaine dimension, affichées à l'écran sont toujours un de moins que le nombre maximum de voxels que les dimensions. Par exemple, si X1 = X2 = X3 = 10, le nombre de voxels dans chaque dimension qui sont affichés sur vtkwindow est 9. Ce n'est pas ce que je m'attendais. Je pense que c'est le problème avec X1 = 1, ce qui rend 1-1 = 0 affichage voxel. Des suggestions?

+0

Donc, vos données ne deviennent pas vraiment 2D, il est juste un une seule couche de voxels? Avez-vous vérifié si le nombre de cellules de vos données d'image monocouche est ce que vous attendez? Peut-être qu'il y a une sorte de problème de numérotation, mais c'est difficile à dire sans voir plus de code. – mululu

+0

Oui, ce n'est qu'une seule couche de voxels. J'ai vérifié le nombre de cellules dans les données d'image monocouche, c'est comme prévu. Je posterai bientôt le code équivalent minimal. –

Répondre

1

Ceci est resté longtemps sans réponse. Donc, j'ajoute ma solution/solution de contournement. Je devais ajouter une couche fictive supplémentaire dans chaque dimension d'imagedata. [Voir cette ligne dans le code imageData-> SetDimensions (X1 +1, X2 + 1, X3 + 1);]. Le repos est explicite.

#pragma once 
//#include <vtkAutoInit.h> // if not using CMake to compile, necessary to use this macro 
//#define vtkRenderingCore_AUTOINIT 3(vtkInteractionStyle, vtkRenderingFreeType, vtkRenderingOpenGL2) 
//#define vtkRenderingVolume_AUTOINIT 1(vtkRenderingVolumeOpenGL2) 
//#define vtkRenderingContext2D_AUTOINIT 1(vtkRenderingContextOpenGL2) 
#include <vtkSmartPointer.h> 
#include <vtkActor.h> 
#include <vtkRenderWindow.h> 
#include <vtkRenderer.h> 
#include <vtkRenderWindowInteractor.h> 
#include <vtkSmartVolumeMapper.h> 
#include <vtkColorTransferFunction.h> 
#include <vtkVolumeProperty.h> 
#include <vtkSampleFunction.h> 
#include <vtkPiecewiseFunction.h> 
#include <vtkImageData.h> 
#include <stdlib.h> 
#include <numeric>  // std::iota 
using namespace std; 

int main() 
{ 
    //Declaring Variables 
    vtkSmartPointer<vtkImageData> imageData; 
    vtkSmartPointer<vtkVolumeProperty> volumeProperty; 
    vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity; 
    vtkSmartPointer<vtkColorTransferFunction> color; 
    vtkSmartPointer<vtkVolume> volume; 
    vtkSmartPointer<vtkSmartVolumeMapper> mapper; 
    vtkSmartPointer<vtkActor> actor; 
    vtkSmartPointer<vtkRenderer> renderer; 
    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor; 
    vtkSmartPointer<vtkRenderWindow> renderWindow; 
    int X1, X2, X3, X1X2X3; 
    //Assigning Values , Allocating Memory 
    X1 = 10; 
    X2 = 10; 
    X3 = 10; 
    X1X2X3 = X1*X2*X3; 
    imageData = vtkSmartPointer<vtkImageData>::New(); 
    imageData->SetDimensions(X1 + 1, X2 + 1, X3 + 1); 
    imageData->AllocateScalars(VTK_INT, 1); 
    volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New(); 
    compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New(); 
    color = vtkSmartPointer<vtkColorTransferFunction>::New(); 
    volume = vtkSmartPointer<vtkVolume>::New(); 
    mapper = vtkSmartPointer<vtkSmartVolumeMapper>::New(); 
    actor = vtkSmartPointer<vtkActor>::New(); 
    renderer = vtkSmartPointer<vtkRenderer>::New(); 
    renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); 
    renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); 
    volumeProperty->ShadeOff(); 
    volumeProperty->SetInterpolationType(0); 
    volumeProperty->SetColor(color); 
    volumeProperty->SetScalarOpacity(compositeOpacity); 
    imageData->AllocateScalars(VTK_INT, 1); 
    renderWindow->AddRenderer(renderer); 
    renderWindowInteractor->SetRenderWindow(renderWindow); 
    renderer->SetBackground(0.5, 0.5, 0.5); 
    renderWindow->SetSize(800, 800); 
    mapper->SetBlendModeToComposite(); 
    imageData->UpdateCellGhostArrayCache(); 
    mapper->SetRequestedRenderModeToRayCast(); 
    mapper->SetInputData(imageData); 
    volume->SetMapper(mapper); 
    volume->SetProperty(volumeProperty); 
    renderer->AddViewProp(volume); 
    volumeProperty->ShadeOff(); 

    //I is supposed to store the 3D data which has to be shown as volume visualization. This 3D data is stored 
    //as a 1D array in which the order of iteration over 3 dimensions is x->y->z, this leads to the following 
    //3D to 1D index conversion farmula index1D = i + X1*j + X1*X2*k 
    vector<int> I(X1X2X3,0); // No need to use int* I = new int[X1X2X3] //Vectors are good 
    std::iota(&I[0], &I[0] + X1X2X3, 1); //Creating dummy data as 1,2,3...X1X2X3 

    //Setting Voxel Data and Its Properties 
    for (int k = 0; k < X3 + 1 ; k++) 
    { 
     for (int j = 0; j < X2 + 1 ; j++) 
     { 
      for (int i = 0; i < X1 + 1 ; i++) 
      { 
       int* voxel = static_cast<int*>(imageData->GetScalarPointer(i, j, k)); 

       if (i==X1 || j== X2 || k==X3) 
       { 
        //Assigning zeros to dummy voxels, these will not be displayed anyways 
        voxel[0] = 0; 
       } 

       else 
       { 
        //copying data from I to imagedata voxel 
        voxel[0] = I[i + X1*j + X1*X2*k]; 
       }    
      } 
     } 
    } 

    //Setting Up Display Properties 
    for (int i = 1; i < X1X2X3; i++) 
    { 
     compositeOpacity->AddPoint(i, 1); 
     color->AddRGBPoint(i, double(rand())/RAND_MAX, double(rand())/RAND_MAX, double(rand())/RAND_MAX); 
    } 

    renderer->ResetCamera(); 
    renderWindow->Render(); 
    renderWindowInteractor->Start(); 
    getchar(); 
    return 0; 
} 

Maintenant, le nombre prévu de voxels dans chaque dimension (10 selon le code ci-dessus), sont vus correctement

enter image description here