1
votes

I used vtkDICOMImageReader to read the DICOM file. I used the vtkImageThreshold to threshold a CT image. And now i want to write it back to my hard disk before further processing.

I tried vtkImageWriter library to write it back. But it is not working when i try to open the file using 3D slicer. I am much grateful if anyone can suggest me a methodology for writing Dicom files.

i have included my code here and i am trying to threshold a dicom image and viewing it. Then i would like to save the thresholded image as a dicom file. But i could not succeed in doing that. please help me.

thanks in advance.

#include <itkImageToVTKImageFilter.h>
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkImageThreshold.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkImageMapper3D.h>
#include <vtkImageActor.h>
#include <vtkImageCast.h>
#include <vtkNIFTIImageWriter.h>
#include <vtkImageMandelbrotSource.h>
#include <vtkImageViewer2.h>
#include <vtkDICOMImageReader.h>

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

std::string folder = argv[1];

vtkSmartPointer<vtkDICOMImageReader> reader =
      vtkSmartPointer<vtkDICOMImageReader>::New();
reader->SetFileName(folder.c_str());
reader->Update();

vtkSmartPointer<vtkImageViewer2> imageViewer =
  vtkSmartPointer<vtkImageViewer2>::New();
imageViewer->SetInputConnection(reader->GetOutputPort());

// threshold the images
vtkSmartPointer<vtkImageThreshold> imageThreshold = 
    vtkSmartPointer<vtkImageThreshold>::New();
imageThreshold->SetInputConnection(reader->GetOutputPort());
// unsigned char lower = 127;
unsigned char upper = 511;

imageThreshold->ThresholdByLower(upper);
imageThreshold->ReplaceInOn();
imageThreshold->SetInValue(0);
imageThreshold->ReplaceOutOn();
imageThreshold->SetOutValue(511);
imageThreshold->Update();

// Create actors
vtkSmartPointer<vtkImageActor> inputActor =
  vtkSmartPointer<vtkImageActor>::New();
inputActor->GetMapper()->SetInputConnection(
  reader->GetOutputPort());

vtkSmartPointer<vtkImageActor> thresholdedActor =
vtkSmartPointer<vtkImageActor>::New();
thresholdedActor->GetMapper()->SetInputConnection(
imageThreshold->GetOutputPort());

// There will be one render window
vtkSmartPointer<vtkRenderWindow> renderWindow =
  vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(600, 300);

// And one interactor
vtkSmartPointer<vtkRenderWindowInteractor> interactor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor->SetRenderWindow(renderWindow);

// Define viewport ranges
// (xmin, ymin, xmax, ymax)
double leftViewport[4] = {0.0, 0.0, 0.5, 1.0};
double rightViewport[4] = {0.5, 0.0, 1.0, 1.0};

// Setup both renderers
vtkSmartPointer<vtkRenderer> leftRenderer =
  vtkSmartPointer<vtkRenderer>::New();
renderWindow->AddRenderer(leftRenderer);
leftRenderer->SetViewport(leftViewport);
leftRenderer->SetBackground(.6, .5, .4);

vtkSmartPointer<vtkRenderer> rightRenderer =
  vtkSmartPointer<vtkRenderer>::New();
renderWindow->AddRenderer(rightRenderer);
rightRenderer->SetViewport(rightViewport);
rightRenderer->SetBackground(.4, .5, .6);

leftRenderer->AddActor(inputActor);
rightRenderer->AddActor(thresholdedActor);

leftRenderer->ResetCamera();
rightRenderer->ResetCamera();

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

vtkSmartPointer<vtkNIFTIImageWriter> writer =
  vtkSmartPointer<vtkNIFTIImageWriter>::New();
writer->SetInputConnection(reader->GetOutputPort());
writer->SetFileName("output");
writer->Write();

// writing the thresholded image to the hard drive.
//this is the part i am not able to code. Please can somebody help me     please? 

return EXIT_SUCCESS;

 }
2
You'll have to show your code for anyone to be able to helpjohn elemans
thanks for commenting. can you please check the code and tell me how to savw the thresholded image in dicom format?Sachith Bathiya

2 Answers

0
votes

First, do you want to save out the thresholded image or just the image as read in? If not replace reader with imageThreshold

writer->SetInputConnection(reader->GetOutputPort())

From looking at the VTK tests of NIFTI readers and writers the following options may be required...

writer->SetNIFTIHeader(reader->GetNIFTIHeader())
writer->SetQFac(reader->GetQFac());
writer->SetTimeDimension(reader->GetTimeDimension());
writer->SetTimeSpacing(reader->GetTimeSpacing());
writer->SetRescaleSlope(reader->GetRescaleSlope());
writer->SetRescaleIntercept(reader->GetRescaleIntercept());
writer->SetQFormMatrix(reader->GetQFormMatrix()); 

I would test with adding these options and then see what you get

0
votes

I think VTK is a little bit confused to process image. I only use it to display image.I wrote a piece of code for you. The code which read , threshold and write dicom image is below.It use only itk. I think it fills the bill.

    #include "itkBinaryThresholdImageFilter.h"
    #include "itkImageFileReader.h"
    #include "itkGDCMImageIO.h"
    #include "itkImageFileWriter.h"
    #include "itkImage.h"

    int main () {
    typedef unsigned char InputPixelType ;  //Pixel Type of Input image
    typedef unsigned char OutputPixelType;  //Pixel Type of Output image
    const unsigned int InputDimension = 2;  //Dimension of image

    typedef itk::Image < InputPixelType, InputDimension > InputImageType; //Type definition of Input Image
    typedef itk::Image < InputPixelType, InputDimension > OutputImageType;//Type definition of Output Image
    typedef itk::ImageSeriesReader< InputImageType > ReaderType;//Type definition of Reader  
    typedef itk::BinaryThresholdImageFilter<InputImageType, OutputImageType > FilterType; // Type definition of Filter
    typedef itk::ImageFileWriter<OutputImageType> ImageWriterType; //Definition of Writer of Ouput image
    typedef itk::GDCMImageIO ImageIOType; //Type definition of Image IO for Dicom images

//Starts Reading Process
    ReaderType::Pointer reader = ReaderType::New(); //Creates reader
    ImageIOType::Pointer gdcmImageIO_input = ImageIOType::New(); //Creates ImageIO object for input image

    reader->SetImageIO( gdcmImageIO_input ); // Sets image IO of reader
    reader->SetFileNames( "example_image.dcm" ); // Sets filename to reader

//Exceptional handling
    try
    {
          reader->UpdateLargestPossibleRegion();
    }
    catch (itk::ExceptionObject & e)
    {
          std::cerr << "exception in file reader " << std::endl;
          std::cerr << e << std::endl;
          return EXIT_FAILURE;
    }
// Start filtering process
    FilterType::Pointer filter = FilterType::New(); //Creates filter
    filter->SetInput( reader->GetOutput() );
    filter->SetOutsideValue( 0);  // Set pixel value which are out of lower and upper threshold value
    filter->SetInsideValue( 255 );// Set pixel value which are within lower and upper threshold value
    filter->SetLowerThreshold( 25 ); // Lower threshold value 25
    filter->SetUpperThreshold( 150 );// Upper threshold value 150
    filter->Update();


//Starts Writing Process

    ImageWriterType::Pointer imageWriter = ImageWriterType::New(); // Creates writer
    ImageIOType::Pointer gdcmImageIO_output = ImageIOType::New(); // Creates Image IO object for output image

    imageWriter->SetImageIO( gdcmImageIO_output ); // Set image IO as dicom
    imageWriter->SetInput(filter->GetOutput() );  // Connects output of filter with to input of writer
    imageWriter->SetFileName(example_image_thresholded.dcm); // Sets output file name
//Exceptional handling
    try
      {
      imageWriter->Update();
      }
    catch ( itk::ExceptionObject &exception )
      {
      std::cerr << "Exception in file writer ! " << std::endl;
      std::cerr << exception << std::endl;

      return EXIT_FAILURE;
      }
    return EXIT_SUCCESS;
    }