Reading image series

Hi all, How can I read images series in ITK which are in NRRD format ?

Hello @basal,

In C++, you can use itk::ImageSeriesReader. Here is an example:

https://itk.org/ITKExamples/src/IO/ImageBase/Creade3DFromSeriesOf2D/Documentation.html?highlight=imageseriesreader

In Python, you can just past a list of filenames to itk.imread.

files = ['1.nrrd', '2.nrrd', '3.nrrd']
image= itk.imread(files)

HTH,
Matt

2 Likes

Hi Matt,
Thank you for your reply, do you know how I can define the argument values? My images are output000.nrrd till output048.nrrd, I mean I have 49 slices (2D images) and need to get 3D volume or 3D image of them. For the c++ code that you kindly sent, I inserted the argument values like this:
output000.nrrd 0 48 3Dout.nrrd , but it doesn’t work.
Could you please help me about defining the input for this code?

Thanks

Try argument using printf-like syntax, such as: output%3d.nrrd 0 48 3Dout.nrrd

1 Like

Thanks for the reply, actually, I changed this line nameGenerator->SetSeriesFormat(argv[1]); to
std::string format = argv[1];
format += “%03d.”;
format += argv[2]; // filename extension
nameGenerator->SetSeriesFormat(format.c_str());

and put the argument values :
output nrrd 0 48 3Dout.nrrd
and it works.
Now, my problem is that the size of the output image in coronal and sagittal plans are different from the ones which are in main 3D image. Do you have any idea to fix it?
Thanks.

Select only a subset of slices, e.g. all coronal slices -> coronal3Dimage.

Actually, I do not understand what you mean exactly. Can you explain more? In addition, I need to view all planes in 3D slicer.

No matter how you read the image, once you have a 3D image you can view all planes in 3D Slicer. If all your input slices are in same orientation (e.g. axial), there is no problem. Otherwise, slices e.g. 0…10 make an axial image, and e.g. 11…47 make coronal.

yes, all of my slices are in the axial plane. But still, I am getting different image sizes for sagittal and coronal plans.

I don’t understand what is the problem, please explain it in more detail, possibly with images/screenshots.

Pictures.rar (674.1 KB)

I sent you the images, one of them is the result of the code and other is the main image. they should be in the same size in all planes but they are in the same size just in axial view.

The spacing along axial direction is not 1.0, but larger. A series of .nrrd slices probably does not encode 3D spatial position like a series of DICOM slices, so you have to know ‘Z’ spacing and set it manually in code after reading the image, e.g. image->GetSpacing()[2]=4.4;.

1 Like

Thank you very much for your answer. Both origin and spacing in Z direction are different. So, I wrote the following code, but it gives me a debug error. Can you take a look at the code and kindly let me know what the problem is?

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
// Software Guide : EndCodeSnippet
#include "itkImage.h"
#include "itkVersor.h"
#include "itkChangeInformationImageFilter.h"
int main(int argc, char ** argv)
{
	// Verify the number of parameters in the command line
	if (argc < 3)
	{
		std::cerr << "Usage: " << std::endl;
		std::cerr << argv[0] << " inputImageFile  outputImageFile " << std::endl;
		return EXIT_FAILURE;
	}
	using PixelType = unsigned short;
	constexpr unsigned int Dimension = 3;
	
	using ImageType = itk::Image< PixelType, Dimension >;
	using ReaderType = itk::ImageFileReader< ImageType >;
	using WriterType = itk::ImageFileWriter< ImageType >;

	ReaderType::Pointer reader = ReaderType::New();
	WriterType::Pointer writer = WriterType::New();
	const char * inputFilename = argv[1];
	const char * outputFilename = argv[2];
	using InputImageType = itk::Image<PixelType, Dimension>;
	ImageType::Pointer image = ImageType::New();
	reader->Update();
	reader->SetFileName(inputFilename);
	writer->SetFileName(outputFilename);
	ImageType::ConstPointer inputImage = reader->GetOutput();
	
	using FilterType = itk::ChangeInformationImageFilter<ImageType>;
	FilterType::Pointer filter = FilterType::New();
	filter->SetInput(reader->GetOutput());
	ImageType::PointType::VectorType spacing;
	spacing[2] = 3;
	filter->SetOutputSpacing(spacing);
	filter->ChangeSpacingOn();

	ImageType::PointType origin = inputImage->GetOrigin();
	origin[2]= -667;
	filter->SetOutputOrigin(origin);
	filter->ChangeOriginOn();
	writer->SetInput(filter->GetOutput());
	try
	{
		writer->Update();
	}
	catch (itk::ExceptionObject & err)
	{
		std::cerr << "ExceptionObject caught !" << std::endl;
		std::cerr << err << std::endl;
		return EXIT_FAILURE;
	}
	return EXIT_SUCCESS;
}

reader->SetFileName(inputFilename); must come before reader->Update();.

1 Like

Thanks. I changed it, now the output in 3D slicer is black. Do you any idea? Is the way I used for changing origin and spacing correct?

You might need to change your pixel type using PixelType = unsigned short; to something bigger or signed.