[vtkusers] Create vtkVolume from a dicom series files
Mercusyo
gregory.baert at inserm.fr
Wed Jan 6 04:29:56 EST 2016
Hello,
Thanks for your help;
So, I used the "ReadDicomSeries" project and modified it as follow :
//
// This example demonstrates how to read a series of dicom images
// and how to scroll with the mousewheel or the up/down keys
// through all slices
//
// some standard vtk headers
#include <vtkSmartPointer.h>
#include <vtkObjectFactory.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkActor.h>
// headers needed for this example
#include <vtkImageViewer2.h>
#include <vtkDICOMImageReader.h>
#include <vtkInteractorStyleImage.h>
#include <vtkActor2D.h>
#include <vtkTextProperty.h>
#include <vtkTextMapper.h>
// Pour le volume
#include <vtkVolume.h>
#include <vtkVolumeProperty.h>
#include <vtkImageClip.h>
#include <vtkPiecewiseFunction.h>
#include <vtkColorTransferFunction.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
// needed to easily convert int to std::string
#include <sstream>
// helper class to format slice status message
class StatusMessage
{
public:
static std::string Format(int slice, int maxSlice)
{
std::stringstream tmp;
tmp << "Slice Number " << slice + 1 << "/" << maxSlice + 1;
return tmp.str();
}
};
// Define own interaction style
class myVtkInteractorStyleImage : public vtkInteractorStyleImage
{
public:
static myVtkInteractorStyleImage* New();
vtkTypeMacro(myVtkInteractorStyleImage, vtkInteractorStyleImage);
protected:
vtkImageViewer2* _ImageViewer;
vtkTextMapper* _StatusMapper;
int _Slice;
int _MinSlice;
int _MaxSlice;
public:
void SetImageViewer(vtkImageViewer2* imageViewer) {
_ImageViewer = imageViewer;
_MinSlice = imageViewer->GetSliceMin();
_MaxSlice = imageViewer->GetSliceMax();
_Slice = _MinSlice;
cout << "Slicer: Min = " << _MinSlice << ", Max = " << _MaxSlice <<
std::endl;
}
void SetStatusMapper(vtkTextMapper* statusMapper) {
_StatusMapper = statusMapper;
}
protected:
void MoveSliceForward() {
if(_Slice < _MaxSlice) {
_Slice += 1;
cout << "MoveSliceForward::Slice = " << _Slice << std::endl;
_ImageViewer->SetSlice(_Slice);
std::string msg = StatusMessage::Format(_Slice, _MaxSlice);
_StatusMapper->SetInput(msg.c_str());
_ImageViewer->Render();
}
}
void MoveSliceBackward() {
if(_Slice > _MinSlice) {
_Slice -= 1;
cout << "MoveSliceBackward::Slice = " << _Slice << std::endl;
_ImageViewer->SetSlice(_Slice);
std::string msg = StatusMessage::Format(_Slice, _MaxSlice);
_StatusMapper->SetInput(msg.c_str());
_ImageViewer->Render();
}
}
virtual void OnKeyDown() {
std::string key = this->GetInteractor()->GetKeySym();
if(key.compare("Up") == 0) {
//cout << "Up arrow key was pressed." << endl;
MoveSliceForward();
}
else if(key.compare("Down") == 0) {
//cout << "Down arrow key was pressed." << endl;
MoveSliceBackward();
}
// forward event
vtkInteractorStyleImage::OnKeyDown();
}
virtual void OnMouseWheelForward() {
//std::cout << "Scrolled mouse wheel forward." << std::endl;
MoveSliceForward();
// don't forward events, otherwise the image will be zoomed
// in case another interactorstyle is used (e.g. trackballstyle, ...)
// vtkInteractorStyleImage::OnMouseWheelForward();
}
virtual void OnMouseWheelBackward() {
//std::cout << "Scrolled mouse wheel backward." << std::endl;
if(_Slice > _MinSlice) {
MoveSliceBackward();
}
// don't forward events, otherwise the image will be zoomed
// in case another interactorstyle is used (e.g. trackballstyle, ...)
// vtkInteractorStyleImage::OnMouseWheelBackward();
}
};
vtkStandardNewMacro(myVtkInteractorStyleImage);
int main(int argc, char* argv[])
{
// Verify input arguments
if (argc != 2)
{
std::cout << "Usage: " << argv[0] << " FolderName" << std::endl;
return EXIT_FAILURE;
}
std::string folder = argv[1];
// Read all the DICOM files in the specified directory.
vtkSmartPointer<vtkDICOMImageReader> reader =
vtkSmartPointer<vtkDICOMImageReader>::New();
reader->SetDirectoryName(folder.c_str());
reader->Update();
// Visualize
vtkSmartPointer<vtkImageViewer2> imageViewer =
vtkSmartPointer<vtkImageViewer2>::New();
imageViewer->SetInputConnection(reader->GetOutputPort());
// slice status message
vtkSmartPointer<vtkTextProperty> sliceTextProp =
vtkSmartPointer<vtkTextProperty>::New();
sliceTextProp->SetFontFamilyToCourier();
sliceTextProp->SetFontSize(20);
sliceTextProp->SetVerticalJustificationToBottom();
sliceTextProp->SetJustificationToLeft();
vtkSmartPointer<vtkTextMapper> sliceTextMapper =
vtkSmartPointer<vtkTextMapper>::New();
std::string msg = StatusMessage::Format(imageViewer->GetSliceMin(),
imageViewer->GetSliceMax());
sliceTextMapper->SetInput(msg.c_str());
sliceTextMapper->SetTextProperty(sliceTextProp);
vtkSmartPointer<vtkActor2D> sliceTextActor =
vtkSmartPointer<vtkActor2D>::New();
sliceTextActor->SetMapper(sliceTextMapper);
sliceTextActor->SetPosition(15, 10);
// usage hint message
vtkSmartPointer<vtkTextProperty> usageTextProp =
vtkSmartPointer<vtkTextProperty>::New();
usageTextProp->SetFontFamilyToCourier();
usageTextProp->SetFontSize(14);
usageTextProp->SetVerticalJustificationToTop();
usageTextProp->SetJustificationToLeft();
vtkSmartPointer<vtkTextMapper> usageTextMapper =
vtkSmartPointer<vtkTextMapper>::New();
usageTextMapper->SetInput("- Slice with mouse wheel\n or Up/Down-Key\n-
Zoom with pressed right\n mouse button while dragging");
usageTextMapper->SetTextProperty(usageTextProp);
vtkSmartPointer<vtkActor2D> usageTextActor =
vtkSmartPointer<vtkActor2D>::New();
usageTextActor->SetMapper(usageTextMapper);
usageTextActor->GetPositionCoordinate()->SetCoordinateSystemToNormalizedDisplay();
usageTextActor->GetPositionCoordinate()->SetValue( 0.05, 0.95);
// create an interactor with our own style (inherit from
vtkInteractorStyleImage)
// in order to catch mousewheel and key events
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<myVtkInteractorStyleImage> myInteractorStyle =
vtkSmartPointer<myVtkInteractorStyleImage>::New();
// make imageviewer2 and sliceTextMapper visible to our interactorstyle
// to enable slice status message updates when scrolling through the
slices
myInteractorStyle->SetImageViewer(imageViewer);
myInteractorStyle->SetStatusMapper(sliceTextMapper);
imageViewer->SetupInteractor(renderWindowInteractor);
// make the interactor use our own interactorstyle
// cause SetupInteractor() is defining it's own default interatorstyle
// this must be called after SetupInteractor()
renderWindowInteractor->SetInteractorStyle(myInteractorStyle);
// add slice status message and usage hint message to the renderer
imageViewer->GetRenderer()->AddActor2D(sliceTextActor);
imageViewer->GetRenderer()->AddActor2D(usageTextActor);
// initialize rendering and interaction
//imageViewer->GetRenderWindow()->SetSize(400, 300);
//imageViewer->GetRenderer()->SetBackground(0.2, 0.3, 0.4);
imageViewer->Render();
imageViewer->GetRenderer()->ResetCamera();
// Create a transfer function mapping scalar value to opacity
vtkSmartPointer<vtkPiecewiseFunction> oTFun =
vtkSmartPointer<vtkPiecewiseFunction>::New();
oTFun->AddSegment(0, 1.0, 256, 0.1);
vtkSmartPointer<vtkColorTransferFunction> cTFun =
vtkSmartPointer<vtkColorTransferFunction>::New();
cTFun->AddRGBPoint( 0, 1.0, 1.0, 1.0 );
cTFun->AddRGBPoint( 255, 1.0, 1.0, 1.0 );
// Need to crop to actually see minimum intensity
vtkSmartPointer<vtkImageClip> clip = vtkSmartPointer<vtkImageClip>::New();
clip->SetInputConnection(reader->GetOutputPort());
clip->SetOutputWholeExtent(0,66,0,66,30,37);
clip->ClipDataOn();
vtkSmartPointer<vtkVolumeProperty> property =
vtkSmartPointer<vtkVolumeProperty>::New();
property->SetScalarOpacity(oTFun);
property->SetColor(cTFun);
property->SetInterpolationTypeToLinear();
vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> mapper =
vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
mapper->SetBlendModeToMinimumIntensity();
mapper->SetInputConnection( clip->GetOutputPort() );
vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
volume->SetMapper(mapper);
volume->SetProperty(property);
imageViewer->GetRenderer()->AddViewProp(volume);
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
But the result is strange (see joined file) Capture.PNG
<http://vtk.1045678.n5.nabble.com/file/n5735808/Capture.PNG>
on the left bottom corner ... is that the volume ?
I don't really understand yet the notion of volume with VTK ...
Best regards,
--
View this message in context: http://vtk.1045678.n5.nabble.com/Create-vtkVolume-from-a-dicom-series-files-tp5735781p5735808.html
Sent from the VTK - Users mailing list archive at Nabble.com.
More information about the vtkusers
mailing list