Image conversion from 3D volume to 2D slices

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;
}

1 Like

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
3 Likes

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

2 Likes

Hi, I was trying to compile your code but I get an exception on the line 314 (nonConstInput->UpdateOutputData(); ) of the itkImageFileWriter.hxx file. Could you give me some suggestions? Thanks in advance.

What is the exception message? What inputs are you passing to the program?

“Unhandled exception at 0x00007FFFC7424F99: Microsoft C ++ exception: itk :: InvalidRequestedRegionError at memory location 0x0000004CDD5AF8E0”. I’m passing a .nii file from the BraTS 2020 training set. Thanks!

Does the input image have at least 43 slices?