Image conversion from 3D volume to 2D slices

(Shrabani Ghosh) #1

I am finding difficulty to convert a 3D nifti image to slices.
Here is a screenshot of input 3D image. 1
And the slices should look like this. 2
But using this code I am getting this type of output slice. slice1

The code is below.
#include “itkImageFileReader.h”
#include “itkImageFileWriter.h”
#include “itkExtractImageFilter.h”
#include “itkImage.h”
#include<string.h>
#include <itkRescaleIntensityImageFilter.h>
int main( int argc, char ** argv )
{

typedef signed short InputPixelType;
typedef unsigned char OutputPixelType;
typedef itk::Image< InputPixelType, 3 > InputImageType;
typedef itk::Image< OutputPixelType, 2 > OutputImageType;
typedef itk::ImageFileReader< InputImageType > ReaderType;
typedef itk::ImageFileWriter< OutputImageType > WriterType;
const char * inputFilename = “G:/My Drive/BMES2019/New folder/subject2.nii”;

{
int i = 1;
std::string str=“input//”;
std::string s1=“slice”;
std::string s2 = std::to_string(i);
std::string s3=".png";
std::string s4=str+s1+s2+s3;
const char *mycharp = s4.c_str();

const char * outputFilename = mycharp;
ReaderType::Pointer reader = ReaderType::New();
WriterType::Pointer writer = WriterType::New();
reader->SetFileName( inputFilename );
writer->SetFileName( outputFilename );

typedef itk::ExtractImageFilter< InputImageType,OutputImageType > FilterType;
FilterType::Pointer filter = FilterType::New();
filter->InPlaceOn();
filter->SetDirectionCollapseToSubmatrix();
reader->UpdateOutputInformation();
InputImageType::RegionType inputRegion = reader->GetOutput()->GetLargestPossibleRegion();

InputImageType::SizeType size = inputRegion.GetSize();
size[2] = 0;

InputImageType::IndexType start = inputRegion.GetIndex();
const unsigned int sliceNumber = stoi(s2);
start[2] = sliceNumber;

InputImageType::RegionType desiredRegion;
desiredRegion.SetSize( size );
desiredRegion.SetIndex( start );

filter->SetExtractionRegion( desiredRegion );

filter->SetInput( reader->GetOutput() );

typedef itk::RescaleIntensityImageFilter< OutputImageType, OutputImageType > RescaleFilterType;
RescaleFilterType::Pointer rescalefilter = RescaleFilterType::New();
rescalefilter->SetInput( filter->GetOutput() );

writer->SetInput( rescalefilter->GetOutput() );
try
{
writer->Update();
}
catch( itk::ExceptionObject & err )
{
std::cerr << “ExceptionObject caught !” << std::endl;
std::cerr << err << std::endl;
getchar();
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}

(Dženan Zukić) #2

Your program changed so it compiles and runs on my computer:

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkExtractImageFilter.h"
#include "itkImage.h"
#include <string>
#include <itkRescaleIntensityImageFilter.h>

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

    typedef signed short InputPixelType;
    typedef unsigned char OutputPixelType;
    typedef itk::Image< InputPixelType, 3 > InputImageType;
    typedef itk::Image< OutputPixelType, 2 > OutputImageType;
    typedef itk::ImageFileReader< InputImageType > ReaderType;
    typedef itk::ImageFileWriter< OutputImageType > WriterType;
    const char * inputFilename = "C:/Misc/Tester/CBCT.nhdr";


    const char * outputFilename = "C:/Misc/Tester/CBCT42.png";
    ReaderType::Pointer reader = ReaderType::New();
    WriterType::Pointer writer = WriterType::New();
    reader->SetFileName(inputFilename);
    writer->SetFileName(outputFilename);

    typedef itk::ExtractImageFilter< InputImageType, OutputImageType > FilterType;
    FilterType::Pointer filter = FilterType::New();
    filter->InPlaceOn();
    filter->SetDirectionCollapseToSubmatrix();
    reader->UpdateOutputInformation();
    InputImageType::RegionType inputRegion = reader->GetOutput()->GetLargestPossibleRegion();

    InputImageType::SizeType size = inputRegion.GetSize();
    size[2] = 0;

    InputImageType::IndexType start = inputRegion.GetIndex();
    const unsigned int sliceNumber = 42;
    start[2] = sliceNumber;

    InputImageType::RegionType desiredRegion;
    desiredRegion.SetSize(size);
    desiredRegion.SetIndex(start);

    filter->SetExtractionRegion(desiredRegion);

    filter->SetInput(reader->GetOutput());

    typedef itk::RescaleIntensityImageFilter< OutputImageType, OutputImageType > RescaleFilterType;
    RescaleFilterType::Pointer rescalefilter = RescaleFilterType::New();
    rescalefilter->SetInput(filter->GetOutput());

    writer->SetInput(rescalefilter->GetOutput());
    try
    {
        writer->Update();
    }
    catch (itk::ExceptionObject & err)
    {
        std::cerr << "ExceptionObject caught !" << std::endl;
        std::cerr << err << std::endl;
        getchar();
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

… and its output:

Corrected program:

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkExtractImageFilter.h"
#include "itkImage.h"
#include <string>
#include <itkRescaleIntensityImageFilter.h>

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

    typedef signed short InputPixelType;
    typedef unsigned char OutputPixelType;
    typedef itk::Image< InputPixelType, 3 > InputImageType;
    typedef itk::Image< InputPixelType, 2 > SliceImageType;
    typedef itk::Image< OutputPixelType, 2 > OutputImageType;
    typedef itk::ImageFileReader< InputImageType > ReaderType;
    typedef itk::ImageFileWriter< OutputImageType > WriterType;
    const char * inputFilename = "C:/Misc/Tester/CBCT.nhdr";


    const char * outputFilename = "C:/Misc/Tester/CBCT42.png";
    ReaderType::Pointer reader = ReaderType::New();
    WriterType::Pointer writer = WriterType::New();
    reader->SetFileName(inputFilename);
    writer->SetFileName(outputFilename);

    typedef itk::ExtractImageFilter< InputImageType, SliceImageType > FilterType;
    FilterType::Pointer filter = FilterType::New();
    filter->InPlaceOn();
    filter->SetDirectionCollapseToSubmatrix();
    reader->UpdateOutputInformation();
    InputImageType::RegionType inputRegion = reader->GetOutput()->GetLargestPossibleRegion();

    InputImageType::SizeType size = inputRegion.GetSize();
    size[2] = 0;

    InputImageType::IndexType start = inputRegion.GetIndex();
    const unsigned int sliceNumber = 42;
    start[2] = sliceNumber;

    InputImageType::RegionType desiredRegion;
    desiredRegion.SetSize(size);
    desiredRegion.SetIndex(start);

    filter->SetExtractionRegion(desiredRegion);

    filter->SetInput(reader->GetOutput());

    typedef itk::RescaleIntensityImageFilter< SliceImageType, OutputImageType > RescaleFilterType;
    RescaleFilterType::Pointer rescalefilter = RescaleFilterType::New();
    rescalefilter->SetInput(filter->GetOutput());

    writer->SetInput(rescalefilter->GetOutput());
    try
    {
        writer->Update();
    }
    catch (itk::ExceptionObject & err)
    {
        std::cerr << "ExceptionObject caught !" << std::endl;
        std::cerr << err << std::endl;
        getchar();
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

… and its output:

These are the changed parts:

typedef itk::Image< InputPixelType, 2 > SliceImageType;
typedef itk::ExtractImageFilter< InputImageType, SliceImageType > FilterType;
typedef itk::RescaleIntensityImageFilter< SliceImageType, OutputImageType > RescaleFilterType;

This does the rescaling after a slice has been extracted. So if a maximum value in slice 7 is 500HU, it will get mapped to 255 in extracted slice. And if maximum in slice 10 is 3000HU, it will get mapped to 255 too. So values will not be comparable across slices. Comparability between slices e.g. maximum value in extracted slice 7 being 42 (=255*(3000/500)), while maximum in slice 10 is 255. To accomplish comparability between slices, first rescale the whole volume to unsigned char and then extract individual slices:

  1. typedef itk::Image< OutputPixelType, 3 > RescaledImageType;
  2. rescale InputImageType into RescaledImageType
  3. extract RescaledImageType into OutputImageType
2 Likes
(Shrabani Ghosh) #3

Thank You very much for your explanation. I am getting correct output now. Thank You so much for your time.

2 Likes