VTK DICOM - eiichiromomma/CVMLAB GitHub Wiki
VTK) DICOM
(複雑なフォーマットのDICOM画像をVTKで使う。
昔フルスクラッチでDICOMを読むプログラムを書いたが非常に面倒。 マルチスライスの画像になると更に複雑になる。 vtkDICOMImageReaderを使うとあっさり画像が取得できる。
サンプル画像
公開されているDICOM画像
前のリンクは404になっていたのでMedical Image Format FAQ - Part 8のDICOM image samplesを参照。
旧情報
ネットで検索すればあちこちに転がっている。
から拝借。
比較的サイズが小さいPNEUMATIX.zip)をソースのあるディレクトリで展開する。 使用する画像のあるディレクトリは
PNEUMATIX/Cardiovascular Heart-Cardiac Function/fl3d-cor
基本処理
vtkのMLで出た使い方
#include <vtkDICOMImageReader.h>
#include <vtkImageViewer.h>
int main(){
vtkDICOMImageReader *reader = vtkDICOMImageReader::New();
vtkImageViewer *viewer = vtkImageViewer::New();
viewer->SetInput(reader->GetOutput());
reader->SetDirectoryName("PNEUMATIX/Cardiovascular Heart-Cardiac Function/fl3d-cor");
reader->Update();
int VolData_Images = viewer->GetWholeZMax ();
for (int i=0;i<=VolData_Images;i++)
{
viewer->SetZSlice(i);
viewer->SetColorWindow(400);
viewer->SetColorLevel(128);
viewer->Render();
}
reader->Delete();
viewer->Delete();
return 0;
}
これだけ仮にvtkDICOM.cxxとでもして保存する。 MakefileはMakefileのひな型を参考に
CC=gcc
CFLAGS = -Wno-deprecated -I /usr/X11R6/include -I /usr/local/include/vtk-5.0
LDLIBS = -L/usr/X11R6/lib -L /usr/local/lib -lvtkRendering -lvtkIO\
-lvtkGraphics -lvtkImaging -lvtkftgl -lvtkfreetype -lGL -lXt -lSM\
-lICE -lSM -lICE -lSM -lICE -lX11 -lXext -lX11 -lXext -lX11 -lXext\
-lvtkFiltering -lvtkCommon -lvtksys -lpthread -lm -lvtkDICOMParser\
-lvtkpng -lvtktiff -lvtkzlib -lvtkjpeg -lvtkexpat -lvtkMPEG2Encode
vtkDICOM:
としておく。 あとは
make
とするだけ。
DICOM画像の全スライスが次々と表示されたら成功。
VolumeRendering
上記のreader->GetOutput()さえ得られれば、VolumeRenderingは出来たも同然っぽいので、VTKのサンプルであるMedical1.cxxのコードに被せてみる。
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include <vtkDICOMImageReader.h>
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkOutlineFilter.h"
#include "vtkCamera.h"
#include "vtkProperty.h"
#include "vtkPolyDataNormals.h"
#include "vtkContourFilter.h"
//for Capture
#include "vtkWindowToImageFilter.h"
#include "vtkPNGWriter.h"
//for Capture
int main(){
vtkRenderer *aRenderer = vtkRenderer::New();
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(aRenderer);
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
vtkDICOMImageReader *reader = vtkDICOMImageReader::New();
reader->SetDirectoryName("PNEUMATIX/Cardiovascular Heart-Cardiac Function/fl3d-cor");
reader->Update();
vtkContourFilter *skinExtractor = vtkContourFilter::New();
skinExtractor->SetInputConnection(reader->GetOutputPort());
skinExtractor->SetValue(0, 500);
vtkPolyDataNormals *skinNormals = vtkPolyDataNormals::New();
skinNormals->SetInputConnection(skinExtractor->GetOutputPort());
skinNormals->SetFeatureAngle(60.0);
vtkPolyDataMapper *skinMapper = vtkPolyDataMapper::New();
skinMapper->SetInputConnection(skinNormals->GetOutputPort());
skinMapper->ScalarVisibilityOff();
vtkActor *skin = vtkActor::New();
skin->SetMapper(skinMapper);
vtkOutlineFilter *outlineData = vtkOutlineFilter::New();
outlineData->SetInputConnection(reader->GetOutputPort());
vtkPolyDataMapper *mapOutline = vtkPolyDataMapper::New();
mapOutline->SetInputConnection(outlineData->GetOutputPort());
vtkActor *outline = vtkActor::New();
outline->SetMapper(mapOutline);
outline->GetProperty()->SetColor(0,0,0);
vtkCamera *aCamera = vtkCamera::New();
aCamera->SetViewUp (0, 0, -1);
aCamera->SetPosition (0, 1, 0);
aCamera->SetFocalPoint (0, 0, 0);
aCamera->ComputeViewPlaneNormal();
aRenderer->AddActor(outline);
aRenderer->AddActor(skin);
aRenderer->SetActiveCamera(aCamera);
aRenderer->ResetCamera ();
aCamera->Dolly(1.5);
aRenderer->SetBackground(1,1,1);
renWin->SetSize(640, 480);
aRenderer->ResetCameraClippingRange ();
iren->Initialize();
iren->Start();
//for Capture
vtkWindowToImageFilter *w2if=vtkWindowToImageFilter::New();
w2if->SetInput(renWin);
vtkPNGWriter *wr=vtkPNGWriter::New();
wr->SetInputConnection(w2if->GetOutputPort());
wr->SetFileName("Capture.png)");
wr->Write();
w2if->Delete();
wr->Delete();
//for Capture
skinExtractor->Delete();
skinNormals->Delete();
skinMapper->Delete();
skin->Delete();
outlineData->Delete();
mapOutline->Delete();
outline->Delete();
aCamera->Delete();
iren->Delete();
renWin->Delete();
aRenderer->Delete();
reader->Delete();
return 0;
}
冗談のような話だがあっさり成功。
比較すれば分かると思うが、殆どMedical1.cxxのままである。 換えたのは読み込みの部分とv16のインスタンスを使っている部分だけの10行もない。 "//for Capture"でくくった部分は画像キャプチャ用に仕込んだコードで、"q"を押して終了した状態の画像をpng形式で保存する。