[vtkusers] Create vtkVolume from a dicom series files

Cory Quammen cory.quammen at kitware.com
Wed Jan 6 09:27:01 EST 2016


Hi,

It looks like your image data from the DICOMs is being displayed as
slices in the window, so that's good. I'm not sure what the brighter
square in the bottom left corner is - could be the volume rendering
you are trying to do.

Maybe try removing this:

  imageViewer->GetRenderer()->AddViewProp(volume);

and see if the bright square goes away.

A vtkImageData contains a volume image as you may be most familiar
with in medical imaging. A vtkVolume is used to represent a
vtkImageData in a volume rendering setup - you don't need it if you
just want to display slices in your program.

HTH,
Cory

On Wed, Jan 6, 2016 at 4:29 AM, Mercusyo <gregory.baert at inserm.fr> wrote:
> 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.
> _______________________________________________
> Powered by www.kitware.com
>
> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
>
> Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ
>
> Search the list archives at: http://markmail.org/search/?q=vtkusers
>
> Follow this link to subscribe/unsubscribe:
> http://public.kitware.com/mailman/listinfo/vtkusers



-- 
Cory Quammen
R&D Engineer
Kitware, Inc.


More information about the vtkusers mailing list