Re: [ITK-users] Reading DICOM series and visualize the volume with VTK

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: [ITK-users] Reading DICOM series and visualize the volume with VTK

Dženan Zukić
Hi Marco,

that is more of a VTK question than ITK one, best directed at [hidden email]. Also, ITK has migrated to a new forum. Please post further ITK-related questions there instead of this mailing list.

Regards,
Dženan

On Fri, Mar 15, 2019 at 12:54 PM Marco Festugato <[hidden email]> wrote:
Hi Dzenan and thank u for your answer 🙂 I've tried to do as u suggested, but i receive an error telling me that my mapper doesnt accept ''scalar cells''...maybe this connector doesnt work with my mapper? i've tried to simply add the 'connector' to my pipeline:

reader -> connector -> mapper -> volume -> renderer -> window

Here's my code if u want to check it (it still needs a bit of cleaning)...i would appreciate it a lot!! I need this to work for my project :'(

 // VTK includes
#include "vtkDICOMImageReader.h"
#include "vtkImageData.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkVolume.h"
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkVolumeProperty.h>
#include <vtkSmartPointer.h>
#include <vtkPiecewiseFunction.h>
#include <vtkVolumeRayCastCompositeFunction.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include <itkImage.h>
#include <itkImageFileReader.h>
#include <itkImageToVTKImageFilter.h>
#include "vtkVersion.h"
#include "vtkImageViewer.h"
#include "vtkImageMapper3D.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkImageActor.h"
#include "vtkInteractorStyleImage.h"
#include "vtkRenderer.h"
#include "itkImage.h"
#include "itkGDCMImageIO.h"
#include "itkGDCMSeriesFileNames.h"
#include "itkImageSeriesReader.h"
#include "itkImageFileWriter.h"

 int main(int argc, char *argv[])
{
    // Verify the number of parameters in the command line
    if( argc < 2)
    {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0] << " DICOMimagesDirectory " << std::endl;
    return EXIT_FAILURE;
    }
 // Software Guide : BeginCodeSnippet
  typedef signed short    PixelType;
  const unsigned int      Dimension = 3;
  typedef itk::Image< PixelType, Dimension > ImageType;
  typedef itk::ImageToVTKImageFilter<ImageType> ConnectorType;

  ConnectorType::Pointer connector = ConnectorType::New();
 
// We use the image type for instantiating the type of the series reader and
// for constructing one object of its type.

  typedef itk::ImageSeriesReader< ImageType >        ReaderType;
  ReaderType::Pointer reader = ReaderType::New();

// A GDCMImageIO object is created and connected to the reader. This object is
// the one that is aware of the internal intricacies of the DICOM format.
//

  typedef itk::GDCMImageIO       ImageIOType;
  ImageIOType::Pointer dicomIO = ImageIOType::New();

  reader->SetImageIO( dicomIO );

  using NamesGeneratorType = itk::GDCMSeriesFileNames;
  NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New();

  nameGenerator->SetUseSeriesDetails( true );
  nameGenerator->SetDirectory( argv[1] );

  try
    {
    std::cout << std::endl << "The directory: " << std::endl;
    std::cout << std::endl << argv[1] << std::endl << std::endl;
    std::cout << "Contains the following DICOM Series: ";
    std::cout << std::endl << std::endl;


// Software Guide : BeginLatex
//
// The GDCMSeriesFileNames object first identifies the list of DICOM series
// present in the given directory. We receive that list in a reference
// to a container of strings and then we can do things like print out all
// the series identifiers that the generator had found. Since the process of
// finding the series identifiers can potentially throw exceptions, it is
// wise to put this code inside a \code{try/catch} block.
//


    typedef std::vector< std::string >    SeriesIdContainer;

    const SeriesIdContainer & seriesUID = nameGenerator->GetSeriesUIDs();

// Given that it is common to find multiple DICOM series in the same directory,
// we must tell the GDCM classes what specific series we want to read. In
// this example we do this by checking first if the user has provided a series
// identifier in the command line arguments. If no series identifier has been
// passed, then we simply use the first series found during the exploration of
// the directory.


    std::string seriesIdentifier;

     seriesIdentifier = seriesUID.begin()->c_str();

    std::cout << std::endl << std::endl;
    std::cout << "Now reading series: " << std::endl << std::endl;
    std::cout << seriesIdentifier << std::endl;
    std::cout << std::endl << std::endl;


// We pass the series identifier to the name generator and ask for all the
// filenames associated to that series. This list is returned in a container of
// strings by the \code{GetFileNames()} method.


    typedef std::vector< std::string >   FileNamesContainer;
    FileNamesContainer fileNames;

    fileNames = nameGenerator->GetFileNames( seriesIdentifier );

//
// The list of filenames can now be passed to the \doxygen{ImageSeriesReader}
// using the \code{SetFileNames()} method.


    reader->SetFileNames( fileNames );

// Finally we can trigger the reading process by invoking the \code{Update()}
// method in the reader. This call as usual is placed inside a \code{try/catch}
// block.

    try
      {
      reader->Update();
      }
    catch (itk::ExceptionObject &ex)
      {
      std::cout << ex << std::endl;
      return EXIT_FAILURE;
      }
}
  catch (itk::ExceptionObject &ex)
    {
    std::cout << ex << std::endl;
    return EXIT_FAILURE;
    }

  // Visualization pipeline

    // Create the renderer, render window and interactor
   vtkRenderer *renderer = vtkRenderer::New();
   vtkRenderWindow *renWin = vtkRenderWindow::New();
   renWin->AddRenderer(renderer);
 
    vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
    iren->SetRenderWindow(renWin);
 
   // Read the data
   vtkImageData *input = nullptr;

/*    vtkDICOMImageReader *reader = vtkDICOMImageReader::New();
// vtkTIFFReader *reader = vtkTIFFReader::New();
   reader->SetFileName(argv[1]); */
   // reader->Update(); // read data


   connector->SetInput(reader->GetOutput());
   
    // Create our volume and mapper
    vtkVolume *volume = vtkVolume::New();
    vtkFixedPointVolumeRayCastMapper *mapper = vtkFixedPointVolumeRayCastMapper::New();
// vtkVolumeRayCastCompositeFunction *compositeFunction = vtkVolumeRayCastCompositeFunction::New();
vtkInteractorStyleTrackballCamera *styleCamera = vtkInteractorStyleTrackballCamera::New();

    // connect up the volume to the property and the mapper
    mapper -> SetInputData( connector -> GetOutput() );
mapper -> SetSampleDistance( 0.1 );

vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();


volumeProperty->SetInterpolationTypeToLinear(); // better image quality but computation's longer


vtkSmartPointer<vtkPiecewiseFunction> scalarOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
vtkSmartPointer<vtkPiecewiseFunction> gradientOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();

  scalarOpacity->AddPoint(0,    0.00);
  scalarOpacity->AddPoint(500,  0.15);
  scalarOpacity->AddPoint(1000, 0.15);
  scalarOpacity->AddPoint(1150, 0.85);


  gradientOpacity->AddPoint(0,   0.0);
  gradientOpacity->AddPoint(90,  0.5);
  gradientOpacity->AddPoint(100, 1.0);


//set the transfer functions to the property
volumeProperty->SetScalarOpacity(scalarOpacity);
volumeProperty->SetGradientOpacity(gradientOpacity);

//set the property to the volume

volume->SetProperty(volumeProperty);

volume->SetMapper( mapper );
    iren -> SetInteractorStyle(styleCamera);
    // Set the default window size
    renWin->SetSize(600,600);
 
    // Add the volume to the scene
    renderer->AddVolume( volume );
   
    // interact with data
    renWin->Render();
    iren -> Start();

 
    return EXIT_SUCCESS;
  }



Inviato da Outlook

Da: Dženan Zukić <[hidden email]>
Inviato: venerdì 15 marzo 2019 17:19
A: Marco Festugato
Cc: [hidden email]
Oggetto: Re: [ITK-users] Reading DICOM series and visualize the volume with VTK
 
Hi Marco,

you could combine that example with VTK VolumeRendering example and connect them using ITKVTKGlue.

Regards,
Dženan

On Fri, Mar 15, 2019 at 7:00 AM Marco Festugato <[hidden email]> wrote:
Hi guys! I'm very new to ITK-VTK...what i have to do is reading 199 dicom
images using ITK and visualize the volume using VTK.
Using the example "DicomSeriesReadImageWrite2" im able to read the series
and create a 3D volume but i dont know how to visualize it with VTK!
Any help? :)
Thank u for your time!

Inviato da Outlook
The ITK community is transitioning from this mailing list to discourse.itk.org. Please join us there!
________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html

Kitware offers ITK Training Courses, for more information visit:
http://www.kitware.com/products/protraining.php

Please keep messages on-topic and check the ITK FAQ at:
http://www.itk.org/Wiki/ITK_FAQ

Follow this link to subscribe/unsubscribe:
https://itk.org/mailman/listinfo/insight-users

_______________________________________________
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:
https://vtk.org/mailman/listinfo/vtkusers
Reply | Threaded
Open this post in threaded view
|

Re: [ITK-users] Reading DICOM series and visualize the volume with VTK

Jon Haitz Legarreta Gorroño
In fact, VTK also transitioned to discourse a few weeks ago:
https://discourse.vtk.org

So for a better experience and to increase your chances of getting an
answer, you'd better post your question at discourse rather than to
the mailing lists.

HTH,
JON HAITZ


On Fri, Mar 15, 2019 at 12:58 PM Dženan Zukić <[hidden email]> wrote:

>
> Hi Marco,
>
> that is more of a VTK question than ITK one, best directed at [hidden email]. Also, ITK has migrated to a new forum. Please post further ITK-related questions there instead of this mailing list.
>
> Regards,
> Dženan
>
> On Fri, Mar 15, 2019 at 12:54 PM Marco Festugato <[hidden email]> wrote:
>>
>> Hi Dzenan and thank u for your answer I've tried to do as u suggested, but i receive an error telling me that my mapper doesnt accept ''scalar cells''...maybe this connector doesnt work with my mapper? i've tried to simply add the 'connector' to my pipeline:
>>
>> reader -> connector -> mapper -> volume -> renderer -> window
>>
>> Here's my code if u want to check it (it still needs a bit of cleaning)...i would appreciate it a lot!! I need this to work for my project :'(
>>
>>  // VTK includes
>> #include "vtkDICOMImageReader.h"
>> #include "vtkImageData.h"
>> #include "vtkRenderer.h"
>> #include "vtkRenderWindow.h"
>> #include "vtkRenderWindowInteractor.h"
>> #include "vtkVolume.h"
>> #include <vtkInteractorStyleTrackballCamera.h>
>> #include <vtkVolumeProperty.h>
>> #include <vtkSmartPointer.h>
>> #include <vtkPiecewiseFunction.h>
>> #include <vtkVolumeRayCastCompositeFunction.h>
>> #include <vtkFixedPointVolumeRayCastMapper.h>
>> #include <itkImage.h>
>> #include <itkImageFileReader.h>
>> #include <itkImageToVTKImageFilter.h>
>> #include "vtkVersion.h"
>> #include "vtkImageViewer.h"
>> #include "vtkImageMapper3D.h"
>> #include "vtkRenderWindowInteractor.h"
>> #include "vtkSmartPointer.h"
>> #include "vtkImageActor.h"
>> #include "vtkInteractorStyleImage.h"
>> #include "vtkRenderer.h"
>> #include "itkImage.h"
>> #include "itkGDCMImageIO.h"
>> #include "itkGDCMSeriesFileNames.h"
>> #include "itkImageSeriesReader.h"
>> #include "itkImageFileWriter.h"
>>
>>  int main(int argc, char *argv[])
>> {
>>     // Verify the number of parameters in the command line
>>     if( argc < 2)
>>     {
>>     std::cerr << "Usage: " << std::endl;
>>     std::cerr << argv[0] << " DICOMimagesDirectory " << std::endl;
>>     return EXIT_FAILURE;
>>     }
>>  // Software Guide : BeginCodeSnippet
>>   typedef signed short    PixelType;
>>   const unsigned int      Dimension = 3;
>>   typedef itk::Image< PixelType, Dimension > ImageType;
>>   typedef itk::ImageToVTKImageFilter<ImageType> ConnectorType;
>>
>>   ConnectorType::Pointer connector = ConnectorType::New();
>>
>> // We use the image type for instantiating the type of the series reader and
>> // for constructing one object of its type.
>>
>>   typedef itk::ImageSeriesReader< ImageType >        ReaderType;
>>   ReaderType::Pointer reader = ReaderType::New();
>>
>> // A GDCMImageIO object is created and connected to the reader. This object is
>> // the one that is aware of the internal intricacies of the DICOM format.
>> //
>>
>>   typedef itk::GDCMImageIO       ImageIOType;
>>   ImageIOType::Pointer dicomIO = ImageIOType::New();
>>
>>   reader->SetImageIO( dicomIO );
>>
>>   using NamesGeneratorType = itk::GDCMSeriesFileNames;
>>   NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New();
>>
>>   nameGenerator->SetUseSeriesDetails( true );
>>   nameGenerator->SetDirectory( argv[1] );
>>
>>   try
>>     {
>>     std::cout << std::endl << "The directory: " << std::endl;
>>     std::cout << std::endl << argv[1] << std::endl << std::endl;
>>     std::cout << "Contains the following DICOM Series: ";
>>     std::cout << std::endl << std::endl;
>>
>>
>> // Software Guide : BeginLatex
>> //
>> // The GDCMSeriesFileNames object first identifies the list of DICOM series
>> // present in the given directory. We receive that list in a reference
>> // to a container of strings and then we can do things like print out all
>> // the series identifiers that the generator had found. Since the process of
>> // finding the series identifiers can potentially throw exceptions, it is
>> // wise to put this code inside a \code{try/catch} block.
>> //
>>
>>
>>     typedef std::vector< std::string >    SeriesIdContainer;
>>
>>     const SeriesIdContainer & seriesUID = nameGenerator->GetSeriesUIDs();
>>
>> // Given that it is common to find multiple DICOM series in the same directory,
>> // we must tell the GDCM classes what specific series we want to read. In
>> // this example we do this by checking first if the user has provided a series
>> // identifier in the command line arguments. If no series identifier has been
>> // passed, then we simply use the first series found during the exploration of
>> // the directory.
>>
>>
>>     std::string seriesIdentifier;
>>
>>      seriesIdentifier = seriesUID.begin()->c_str();
>>
>>     std::cout << std::endl << std::endl;
>>     std::cout << "Now reading series: " << std::endl << std::endl;
>>     std::cout << seriesIdentifier << std::endl;
>>     std::cout << std::endl << std::endl;
>>
>>
>> // We pass the series identifier to the name generator and ask for all the
>> // filenames associated to that series. This list is returned in a container of
>> // strings by the \code{GetFileNames()} method.
>>
>>
>>     typedef std::vector< std::string >   FileNamesContainer;
>>     FileNamesContainer fileNames;
>>
>>     fileNames = nameGenerator->GetFileNames( seriesIdentifier );
>>
>> //
>> // The list of filenames can now be passed to the \doxygen{ImageSeriesReader}
>> // using the \code{SetFileNames()} method.
>>
>>
>>     reader->SetFileNames( fileNames );
>>
>> // Finally we can trigger the reading process by invoking the \code{Update()}
>> // method in the reader. This call as usual is placed inside a \code{try/catch}
>> // block.
>>
>>     try
>>       {
>>       reader->Update();
>>       }
>>     catch (itk::ExceptionObject &ex)
>>       {
>>       std::cout << ex << std::endl;
>>       return EXIT_FAILURE;
>>       }
>> }
>>   catch (itk::ExceptionObject &ex)
>>     {
>>     std::cout << ex << std::endl;
>>     return EXIT_FAILURE;
>>     }
>>
>>   // Visualization pipeline
>>
>>     // Create the renderer, render window and interactor
>>    vtkRenderer *renderer = vtkRenderer::New();
>>    vtkRenderWindow *renWin = vtkRenderWindow::New();
>>    renWin->AddRenderer(renderer);
>>
>>     vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
>>     iren->SetRenderWindow(renWin);
>>
>>    // Read the data
>>    vtkImageData *input = nullptr;
>>
>> /*    vtkDICOMImageReader *reader = vtkDICOMImageReader::New();
>> // vtkTIFFReader *reader = vtkTIFFReader::New();
>>    reader->SetFileName(argv[1]); */
>>    // reader->Update(); // read data
>>
>>
>>    connector->SetInput(reader->GetOutput());
>>
>>     // Create our volume and mapper
>>     vtkVolume *volume = vtkVolume::New();
>>     vtkFixedPointVolumeRayCastMapper *mapper = vtkFixedPointVolumeRayCastMapper::New();
>> // vtkVolumeRayCastCompositeFunction *compositeFunction = vtkVolumeRayCastCompositeFunction::New();
>> vtkInteractorStyleTrackballCamera *styleCamera = vtkInteractorStyleTrackballCamera::New();
>>
>>     // connect up the volume to the property and the mapper
>>     mapper -> SetInputData( connector -> GetOutput() );
>> mapper -> SetSampleDistance( 0.1 );
>>
>> vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
>>
>>
>> volumeProperty->SetInterpolationTypeToLinear(); // better image quality but computation's longer
>>
>>
>> vtkSmartPointer<vtkPiecewiseFunction> scalarOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
>> vtkSmartPointer<vtkPiecewiseFunction> gradientOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
>>
>>   scalarOpacity->AddPoint(0,    0.00);
>>   scalarOpacity->AddPoint(500,  0.15);
>>   scalarOpacity->AddPoint(1000, 0.15);
>>   scalarOpacity->AddPoint(1150, 0.85);
>>
>>
>>   gradientOpacity->AddPoint(0,   0.0);
>>   gradientOpacity->AddPoint(90,  0.5);
>>   gradientOpacity->AddPoint(100, 1.0);
>>
>>
>> //set the transfer functions to the property
>> volumeProperty->SetScalarOpacity(scalarOpacity);
>> volumeProperty->SetGradientOpacity(gradientOpacity);
>>
>> //set the property to the volume
>>
>> volume->SetProperty(volumeProperty);
>>
>> volume->SetMapper( mapper );
>>     iren -> SetInteractorStyle(styleCamera);
>>     // Set the default window size
>>     renWin->SetSize(600,600);
>>
>>     // Add the volume to the scene
>>     renderer->AddVolume( volume );
>>
>>     // interact with data
>>     renWin->Render();
>>     iren -> Start();
>>
>>
>>     return EXIT_SUCCESS;
>>   }
>>
>>
>>
>> Inviato da Outlook
>> ________________________________
>> Da: Dženan Zukić <[hidden email]>
>> Inviato: venerdì 15 marzo 2019 17:19
>> A: Marco Festugato
>> Cc: [hidden email]
>> Oggetto: Re: [ITK-users] Reading DICOM series and visualize the volume with VTK
>>
>> Hi Marco,
>>
>> you could combine that example with VTK VolumeRendering example and connect them using ITKVTKGlue.
>>
>> Regards,
>> Dženan
>>
>> On Fri, Mar 15, 2019 at 7:00 AM Marco Festugato <[hidden email]> wrote:
>>
>> Hi guys! I'm very new to ITK-VTK...what i have to do is reading 199 dicom
>> images using ITK and visualize the volume using VTK.
>> Using the example "DicomSeriesReadImageWrite2" im able to read the series
>> and create a 3D volume but i dont know how to visualize it with VTK!
>> Any help? :)
>> Thank u for your time!
>>
>> Inviato da Outlook
>> The ITK community is transitioning from this mailing list to discourse.itk.org. Please join us there!
>> ________________________________
>> Powered by www.kitware.com
>>
>> Visit other Kitware open-source projects at
>> http://www.kitware.com/opensource/opensource.html
>>
>> Kitware offers ITK Training Courses, for more information visit:
>> http://www.kitware.com/products/protraining.php
>>
>> Please keep messages on-topic and check the ITK FAQ at:
>> http://www.itk.org/Wiki/ITK_FAQ
>>
>> Follow this link to subscribe/unsubscribe:
>> https://itk.org/mailman/listinfo/insight-users
>
> _______________________________________________
> 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:
> https://vtk.org/mailman/listinfo/vtkusers
_______________________________________________
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:
https://vtk.org/mailman/listinfo/vtkusers