2016-03-24 88 views
2

我想更好地理解dicom卷的渲染。從.dcm文件生成和讀取.vtk文件並修改模型

我有一組DICOM圖像的,從中我已經能夠提取軸向,冠狀和矢狀切,如下:

enter image description here

我首先想從頭開始生成3D模型,但似乎太難了。

所以我聽說VTK/ITK,和我一直在使用這個代碼來生成從我組圖像.vtk文件:

http://www.itk.org/Doxygen46/html/IO_2DicomSeriesReadImageWrite2_8cxx-example.html

它的工作原理,但我需要一些解釋:

當我打開與paraview包這個文件,我得到以下結果:

enter image description here

首先,這可能是一個愚蠢的問題,但爲什麼它是藍色的?

有沒有辦法切割和看到模型的內部?

我的目標不是使用ParaView,而且我想製作自己的.vtk讀卡器,我發現這個代碼我不記得在哪裏,我認爲這是應該工作的,但是我只能使用它是什麼都沒有的綠色背景:

#include <vtkPolyDataReader.h> 
#include <vtkSmartPointer.h> 
#include <vtkPolyDataMapper.h> 
#include <vtkActor.h> 
#include <vtkRenderWindow.h> 
#include <vtkRenderer.h> 
#include <vtkRenderWindowInteractor.h> 

int main (int argc, char *argv[]) { 

    // Parse command line arguments                  
    if (argc != 2) { 
    std::cerr << "Usage: " << argv[0] << " Filename(.vtk)" << std::endl; 
    return EXIT_FAILURE; 
    } 

    std::string filename = argv[1]; 

    // Read all the data from the file                 
    vtkSmartPointer<vtkPolyDataReader> reader = vtkSmartPointer<vtkPolyDataReader>::New(); 
    reader->SetFileName(filename.c_str()); 
    reader->Update(); 

    // Visualize                       
    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); 
    mapper->SetInputConnection(reader->GetOutputPort()); 

    vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); 
    actor->SetMapper(mapper); 

    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New(); 
    vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); 
    renderWindow->AddRenderer(renderer); 

    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = 
    vtkSmartPointer<vtkRenderWindowInteractor>::New(); 
    renderWindowInteractor->SetRenderWindow(renderWindow); 

    renderer->AddActor(actor); 
    renderer->SetBackground(.3, .6, .3); // Background color green          

    renderWindow->Render(); 
    renderWindowInteractor->Start(); 

    return EXIT_SUCCESS; 
} 

任何想法爲什麼?我在ParaView中看到我必須激活「音量」模式才能看到我的模型,這裏有類似的東西嗎?

最後一件事,這是非常重要的:是否有可能修改.vtk文件內的3D卷?例如,如果我想改變模型的特定部分的顏色,VTK是否提供允許這樣的工具?

回答

1

很多問題在這裏! 這裏有一些答案。

  • 渲染是藍色的,因爲查找表是paraview中的默認值(從藍色到紅色)。您可以使用color map editor
  • 進行編輯確實有某種方法可以在數據中「剪切」,請查看後面的示例。
  • 的例子不工作,因爲你正在嘗試使用POLYDATA加載vtkImageData(目)讀者
  • 這就是爲什麼你必須選擇的Paraview「音量」,那是因爲你的數據是體積(3D體素陣列)。您可以使用VTK中提供的任何卷映射器執行相同操作。
  • 是的,你可以編輯卷的價值,但是這將導致我們有點遠,現在,如果需要,我們會晚一點到;)

下面是一個完整的例子,上面寫着所有目錄下的DICOM文件,構建一個卷,使用卷渲染來渲染它,並使盒子小部件能夠交互式裁剪該卷。

#include "vtkBoxRepresentation.h" 
#include "vtkBoxWidget2.h" 
#include "vtkCamera.h" 
#include "vtkColorTransferFunction.h" 
#include "vtkCommand.h" 
#include "vtkDICOMImageReader.h" 
#include "vtkGPUVolumeRaycastMapper.h" 
#include "vtkImageData.h" 
#include "vtkInteractorStyle.h" 
#include "vtkInteractorStyleTrackballCamera.h" 
#include "vtkMath.h" 
#include "vtkPiecewiseFunction.h" 
#include "vtkPlanes.h" 
#include "vtkRenderWindow.h" 
#include "vtkRenderWindowInteractor.h" 
#include "vtkRenderer.h" 
#include "vtkVolume.h" 
#include "vtkVolumeProperty.h" 

// Box interaction callback 
class vtkBoxCallback : public vtkCommand 
{ 
public: 
    static vtkBoxCallback *New(){ return new vtkBoxCallback; } 
    vtkGPUVolumeRayCastMapper* m_mapper; 
    vtkPlanes* m_planes; 

    virtual void Execute(vtkObject* a_caller, unsigned long, void*){ 
     vtkBoxWidget2* l_box_wdget = vtkBoxWidget2::SafeDownCast(a_caller); 
     ((vtkBoxRepresentation*)l_box_wdget->GetRepresentation())->GetPlanes(m_planes); 
     this->m_mapper->SetClippingPlanes(m_planes); 
    } 

    vtkBoxCallback(){} 
}; 



int main(int argc, char *argv[]){ 

    // Read volume 
    vtkDICOMImageReader* l_reader = vtkDICOMImageReader::New(); 
    l_reader->SetDirectoryName("C:/PathToDicomFiles/"); 
    l_reader->Update(); 

    // Setup rendering stuff 
    vtkRenderer* l_renderer = vtkRenderer::New(); 
    l_renderer->SetBackground(0.3, 0.3, 0.3); 

    vtkRenderWindow* l_render_windows = vtkRenderWindow::New(); 
    l_render_windows->AddRenderer(l_renderer); 
    l_render_windows->SetSize(900, 900); 

    vtkInteractorStyleTrackballCamera* l_trackball = vtkInteractorStyleTrackballCamera::New(); 

    vtkRenderWindowInteractor* l_iren = vtkRenderWindowInteractor::New(); 
    l_iren->SetInteractorStyle(l_trackball); 
    l_iren->SetRenderWindow(l_render_windows); 
    l_iren->GetInteractorStyle()->SetDefaultRenderer(l_renderer); 
    l_iren->SetDesiredUpdateRate(15); 

    // Make sure we have an opengl context 
    l_render_windows->Render(); 


    // Setup GPU volume raycast mapper 
    vtkGPUVolumeRayCastMapper* l_gpu_mapper = vtkGPUVolumeRayCastMapper::New(); 
    l_gpu_mapper->SetInputConnection(l_reader->GetOutputPort()); 

    // Setup Volume property 
    // Window/Level 
    double wl = 260; 
    double ww = 270; 

    // Color function 
    vtkColorTransferFunction* l_color = vtkColorTransferFunction::New(); 
    l_color->SetColorSpaceToRGB(); 
    l_color->AddRGBPoint(wl - ww/2, 0, 0, 0); 
    l_color->AddRGBPoint(wl - ww/2 + 94 * (ww/255.0), 1., 21./255.0, 27./255.0); 
    l_color->AddRGBPoint(wl - ww/2 + 147 * (ww/255.0), 1., 176./255.0, 9./255.0); 
    l_color->AddRGBPoint(wl - ww/2 + 201 * (ww/255.0), 1., 241./255.0, 39./255.0); 
    l_color->AddRGBPoint(wl - ww/2 + 255 * (ww/255.0), 1, 1, 1.); 
    l_color->Build(); 

    // Opacity function 
    vtkPiecewiseFunction* l_opacity = vtkPiecewiseFunction::New(); 
    l_opacity->AddPoint(wl - ww/2, 0); 
    l_opacity->AddPoint(wl + ww/2, 1); 

    // Volume property, light, shading 
    vtkVolumeProperty* l_volume_property = vtkVolumeProperty::New(); 
    l_volume_property->SetColor(l_color); 
    l_volume_property->SetScalarOpacity(l_opacity); 
    l_volume_property->SetInterpolationTypeToLinear(); 
    l_volume_property->ShadeOn(); 
    l_volume_property->SetAmbient(0.15); 
    l_volume_property->SetDiffuse(0.8); 
    l_volume_property->SetSpecular(0.25); 
    l_volume_property->SetSpecularPower(40); 

    // Put everything together 
    vtkVolume* l_volume = vtkVolume::New(); 
    l_volume->SetProperty(l_volume_property); 
    l_volume->SetMapper(l_gpu_mapper); 
    l_renderer->AddVolume(l_volume); 
    l_renderer->ResetCamera(); 

    // setup Box interactive widget 
    vtkBoxRepresentation* l_box_rep = vtkBoxRepresentation::New(); 
    l_box_rep->SetInsideOut(true); 

    vtkBoxWidget2* l_voi_widget = vtkBoxWidget2::New(); 
    l_voi_widget->SetRepresentation(l_box_rep); 
    l_voi_widget->SetInteractor(l_iren); 
    l_voi_widget->GetRepresentation()->SetPlaceFactor(1.); 
    l_voi_widget->GetRepresentation()->PlaceWidget(l_reader->GetOutput()->GetBounds()); 
    l_voi_widget->SetEnabled(true); 

    vtkPlanes* l_planes = vtkPlanes::New(); 

    vtkBoxCallback* l_callback = vtkBoxCallback::New(); 
    l_callback->m_mapper = l_gpu_mapper; 
    l_callback->m_planes = l_planes; 
    l_voi_widget->AddObserver(vtkCommand::InteractionEvent, l_callback); 

    // Go rendering ! 
    l_iren->Start(); 

    // Memory cleanup 
    l_reader->Delete(); 
    l_renderer->Delete(); 
    l_render_windows->Delete(); 
    l_trackball->Delete(); 
    l_iren->Delete(); 
    l_gpu_mapper->Delete(); 
    l_color->Delete(); 
    l_opacity->Delete(); 
    l_volume_property->Delete(); 
    l_volume->Delete(); 
    l_voi_widget->Delete(); 
    l_planes->Delete(); 
    l_callback->Delete(); 
} 

作爲一般的建議,我建議你閱讀VTK examples這應該可以幫助你瞭解所有的VTK功能。

希望幫助:)

+0

謝謝您的回答,我想你讓我很快樂:DI有關於新的問題了一千了,但我會先了解這段代碼是如何工作的:)事實上,編輯模型中的值現在不是現在,但我只需要知道它是否可能:)再次感謝! – Charrette