Getting Started with the NRRD Format

From KitwarePublic
Revision as of 09:36, 24 March 2006 by Kindlmann (talk | contribs) (link to a more useful wiki page for Nrrd info)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

The NRRD format is a little bit different from other image formats. This format has spatial dimensions and other dimensions. The number of spatial dimensions in the image determines the number of dimensions in the image. Other dimensions are loaded into a Vector and used as the pixel type for the image.


Using NRRD to Load Diffusion Weighted Images

Diffusion weighted image are used to generate the diffusion tensor. This subsequently can be used to generate scalar measures as well as fiber tracts. The use of the NRRD format to describe DTI data is described in greater detail on the NA-MIC Wiki Pages. Here is an example of how to read and write the diffusion weighted images in NRRD format using ITK. Since it was not clear upon looking at only the Doxygen pages for the IO factory method. Here is a basic example of the image format:

  • testNrrd.nhdr
NRRD0005
content: SomeIDNumber42
type: short
dimension: 4
space: right-anterior-superior
sizes: 2 2 2 2
thicknesses:  NaN  NaN 2.5  NaN
space directions: (2,0,0) (0,2.5,0) (0,0,2) none
centerings: cell cell cell none
kinds: space space space list
endian: little
encoding: ascii
space units: "mm" "mm" "mm"
space origin: (0,0,0)
data file: testNrrd.ascii
measurement frame: (1,0,0) (0,0,1) (0,1,0)
modality:=DWMRI
DWMRI_b-value:=1000
DWMRI_gradient_0000:= 0  0  0
DWMRI_gradient_0001:= 1  0  1
  • testNrrd.ascii
2 2
2 2
2 2
2 2
1 1
1 1
1 1
1 1

Here is an outline of a basic program to read and write the NRRD format:

#include <vector>
#include <string>
#include <algorithm>
#include <iostream>

#include <itkImage.h>
#include <itkExceptionObject.h>
#include <itkImageFileWriter.h>
#include <itkImageFileReader.h>
#include <itkMetaDataObject.h>
#include <itkNrrdImageIO.h>



int main(int argc, char* argv[])
{  
  typedef itk::Vector<signed short,2>       VectorType;
  typedef itk::Image<VectorType,3>	    DiffusionImageType;
  typedef DiffusionImageType::Pointer	    DiffusionImagePointer;
   
   
  typedef itk::ImageFileReader<DiffusionImageType> FileReaderType;
  FileReaderType::Pointer reader = FileReaderType::New();
  reader->SetFileName(argv[1]);
  reader->Update();
   
  itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
  // This statement is to be added to the ITK CVS Release
  io->SetNrrdVectorType( nrrdKindList );
  io->SetFileType( itk::ImageIOBase::ASCII );
 
  typedef itk::ImageFileWriter<DiffusionImageType> WriterType;
  WriterType::Pointer nrrdWriter = WriterType::New();
  nrrdWriter->UseInputMetaDataDictionaryOn();
  nrrdWriter->SetInput( reader->GetOutput() );
  nrrdWriter->SetImageIO(io);
  nrrdWriter->SetFileName(argv[2]);
  try
    {
    nrrdWriter->Update();
    }
  catch (itk::ExceptionObject e)
    {
    std::cout << e << std::endl;
    }

  return 0;
}

An alternate approach to the fixed vector size is to use the VectorImage class. Here is the above example code modified to work with Vector Images

#include <vector>
#include <string>
#include <algorithm>
#include <iostream>

#include <itkImage.h>
#include <itkImageSeriesReader.h>
#include <itkGDCMImageIO.h>
#include <itkGDCMSeriesFileNames.h>
#include <itkExceptionObject.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkImageFileWriter.h>
#include <itkImageFileReader.h>
#include <itkMetaDataObject.h>
#include <itkNrrdImageIO.h>
#include <itkVectorImage.h>
#include <itkVariableLengthVector.h>



int main(int argc, char* argv[])
{   
  typedef signed short                      PixelType;
  typedef itk::VectorImage<PixelType,3>	    DiffusionImageType;
  typedef DiffusionImageType::Pointer				DiffusionImagePointer;
    
    
  typedef itk::ImageFileReader<DiffusionImageType, 
  itk::DefaultConvertPixelTraits< PixelType > > FileReaderType;
  FileReaderType::Pointer reader = FileReaderType::New();
  reader->SetFileName(argv[1]);
  reader->Update();
   
  itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
  io->SetNrrdVectorType( nrrdKindList );
  io->SetFileType( itk::ImageIOBase::ASCII );
 
  typedef itk::ImageFileWriter<DiffusionImageType > WriterType;
  WriterType::Pointer nrrdWriter = WriterType::New();
  nrrdWriter->UseInputMetaDataDictionaryOn();
  nrrdWriter->SetInput( reader->GetOutput() );
  nrrdWriter->SetImageIO(io);
  nrrdWriter->SetFileName(argv[2]);
  try
    {
    nrrdWriter->Update();
    }
  catch (itk::ExceptionObject e)
    {
    std::cout << e << std::endl;
    }

  return 0;
}


It should be noted that the order of the data is different after writing with ITK. Since the image values are vectors the vector direction is written out first followed by the spatial dimensions. Here is the header and image that results from running the code listed above on the example image:

  • testNRRD2.nhdr
NRRD0005
# Complete NRRD file format specification at:
# http://teem.sourceforge.net/nrrd/format.html
content: SomeIDNumber42
type: short
dimension: 4
space: right-anterior-superior
sizes: 2 2 2 2
thicknesses:  NaN  NaN  NaN 2.5
space directions: none (-2,0,0) (0,-2.5,0) (0,0,2)
centerings: ??? cell cell cell
kinds: list space space space
encoding: ASCII
space origin: (0,0,0)
measurement frame: (1,0,0) (0,0,1) (0,1,0)
data file: testNRRD2.ascii
DWMRI_b-value:=1000
DWMRI_gradient_0000:= 0  0  0
DWMRI_gradient_0001:= 1  0  1
ITK_InputFilterName:=NrrdImageIO
modality:=DWMRI
  • testNRRD2.ascii
2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1

Formatting Diffusion Tensor Weighted DICOM Images into NRRD Format



ITK: [Welcome | Site Map]