Reading and Writing for Images and Transforms¶
Images¶
There are numerous file formats support by SimpleITK’s image readers and writers.
Support for a particular format is handled by a specific ITK
ImageIO class.
By default, the ImageIO is automatically determined for a particular file based
on the file name suffix and/or the contents of the file’s header.
Advanced SimpleITK installations can configure or extend which file formats
are supported by SimpleITK. A list of registered ImageIO’s can be found using the
GetRegisteredImageIOs()
method, but is posted here:
BMPImageIO ( *.bmp, *.BMP )
BioRadImageIO ( *.PIC, *.pic )
GiplImageIO ( *.gipl *.gipl.gz)
JPEGImageIO ( *.jpg, *.JPG, *.jpeg, *.JPEG )
LSMImageIO ( *.tif, *.TIF, *.tiff, *.TIFF, *.lsm, *.LSM )
MINCImageIO ( *.mnc, *.MNC )
MRCImageIO ( *.mrc, *.rec )
MetaImageIO ( *.mha, *.mhd )
NiftiImageIO ( *.nia, *.nii, *.nii.gz, *.hdr, *.img, *.img.gz )
NrrdImageIO ( *.nrrd, *.nhdr )
PNGImageIO ( *.png, *.PNG )
TIFFImageIO ( *.tif, *.TIF, *.tiff, *.TIFF )
VTKImageIO ( *.vtk )
A read and write example using SimpleITK’s ImageFileReader and ImageFileWriter classes:
ImageFileReader reader = new ImageFileReader();
reader.SetImageIO("PNGImageIO");
reader.SetFileName(inputImageFileName);
Image image = reader.Execute();
ImageFileWriter writer = new ImageFileWriter();
writer.SetFileName(outputImageFileName);
writer.Execute(image);
itk::simple::ImageFileReader reader;
reader.SetImageIO("PNGImageIO");
reader.SetFileName(inputImageFileName);
itk::simple::Image image;
image = reader.Execute();
itk::simple::ImageFileWriter writer;
writer.SetFileName(outputImageFileName);
ImageFileReader reader = new ImageFileReader();
reader.setImageIO("PNGImageIO");
reader.setFileName(inputImageFileName);
Image image = reader.execute();
ImageFileWriter writer = new ImageFileWriter();
writer.setFileName(outputImageFileName);
writer.execute(image);
require "SimpleITK"
reader = SimpleITK.ImageFileReader()
reader:SetImageIO("PNGImageIO")
reader:SetFileName(inputImageFileName)
image = reader:Execute();
writer = SimpleITK.ImageFileWriter()
writer:SetFileName(outputImageFileName)
writer:Execute(image);
import SimpleITK as sitk
reader = sitk.ImageFileReader()
reader.SetImageIO("PNGImageIO")
reader.SetFileName(inputImageFileName)
image = reader.Execute()
writer = sitk.ImageFileWriter()
writer.SetFileName(outputImageFileName)
writer.Execute(image)
library(SimpleITK)
reader <- ImageFileReader()
reader$SetImageIO("PNGImageIO")
reader$SetFileName(inputImageFileName)
image <- reader$Execute()
writer <- ImageFileWriter()
writer$SetFileName(outputImageFileName)
writer$Execute(image)
require 'simpleitk'
reader = Simpleitk::ImageFileReader.new
reader.set_image_io("PNGImageIO")
reader.set_file_name(inputImageFileName)
image = reader.execute
writer = Simpleitk::ImageFileWriter.new
writer.set_file_name outputImageFileName
writer.execute image
ImageFileReader reader
reader SetImageIO "PNGImageIO"
reader SetFileName $inputImageFileName
set image [ reader Execute ]
ImageFileWriter writer
writer SetFileName $outputImageFileName
writer Execute $image
reader -delete
writer -delete
$image -delete
The above example specifies using the PNGImageIO to read the file. If that line is omitted, SimpleITK would determine which IO to use automatically, based on the file name’s suffix and/or the file’s header.
A more compact example using SimpleITK’s procedural interface:
Image image = sitk.ReadImage(inputImageFileName, PixelIDValueEnum.sitkUnknown, "PNGImageIO");
sitk.WriteImage(image, outputImageFileName);
itk::simple::Image image;
image = itk::simple::ReadImage(inputImageFileName, itk::simple::sitkUnknown, "PNGImageIO");
Image image = SimpleITK.readImage(inputImageFileName, PixelIDValueEnum.sitkUnknown, "PNGImageIO");
SimpleITK.writeImage(image, outputImageFileName);
require "SimpleITK"
image = SimpleITK.ReadImage(inputImageFileName, SimpleITK.sitkUnknown, "PNGImageIO")
SimpleITK.WriteImage(image, outputImageFileName)
import SimpleITK as sitk
image = sitk.ReadImage(inputImageFileName, imageIO="PNGImageIO")
sitk.WriteImage(image, outputImageFileName)
library(SimpleITK)
image <- ReadImage(inputImageFileName)
WriteImage(image, outputImageFileName)
require 'simpleitk'
image = Simpleitk::read_image(inputImageFileName, Simpleitk::SitkUnknown, "PNGImageIO")
Simpleitk::write_image(image, outputImageFileName)
global sitkUnknown
set image [ ReadImage $inputImageFileName $sitkUnknown "PNGImageIO" ]
WriteImage $image $outputImageFileName
$image -delete
Similarly, if the imageIO parameter is omitted, SimpleITK will determine which IO to use automatically.
Transformations¶
In SimpleITK, transformation files can be written in several different formats. Just as there are numerous IOs for images, there are several for transforms, including TxtTransformIO, MINCTransformIO, HDF5TransformIO, and MatlabTransformIO (although this list can be extended as well). These support a variety of file formats, including .txt, .tfm, .xfm, .hdf and .mat.
Because of the size of displacement fields, writing them may require more careful attention. To save a displacement field we recommend using one of the binary transformation file formats (e.g. .hdf, .mat). Saving it in a text based format results in significantly larger files and longer IO runtimes. Another option is to save the displacement field found in a DisplacementFieldTransform object as an image (.nrrd, .nhdr, .mha, .mhd, .nii, .nii.gz).
Here is a simple example of creating a transformation, writing it to a file, reading it back, and then comparing the results.
Euler2DTransform basic_transform = new Euler2DTransform();
VectorDouble trans = new VectorDouble( new double[] {2.0, 3.0} );
basic_transform.SetTranslation(trans);
sitk.WriteTransform(basic_transform, "euler2D.tfm");
Transform read_result = sitk.ReadTransform("euler2D.tfm");
Debug.Assert( basic_transform.GetName() != read_result.GetName() );
itk::simple::Euler2DTransform basic_transform;
basic_transform.SetTranslation(std::vector<double> {2.0, 3.0});
itk::simple::WriteTransform(basic_transform, "euler2D.tfm");
itk::simple::Transform read_result = itk::simple::ReadTransform("euler2D.tfm");
Euler2DTransform basic_transform = new Euler2DTransform();
double[] t = {2.0, 3.0};
VectorDouble trans = new VectorDouble(t);
basic_transform.setTranslation(trans);
SimpleITK.writeTransform(basic_transform, "euler2D.tfm");
Transform read_result = SimpleITK.readTransform("euler2D.tfm");
assert basic_transform.getClass() != read_result.getClass();
require "SimpleITK"
basic_transform = SimpleITK.Euler2DTransform()
trans = SimpleITK.VectorDouble()
trans:push_back(2.0)
trans:push_back(3.0)
basic_transform:SetTranslation(trans)
SimpleITK.WriteTransform(basic_transform, 'euler2D.tfm')
read_result = SimpleITK.ReadTransform('euler2D.tfm')
assert(read_result:GetName() ~= basic_transform:GetName(), "type error")
import SimpleITK as sitk
basic_transform = sitk.Euler2DTransform()
basic_transform.SetTranslation((2, 3))
sitk.WriteTransform(basic_transform, "euler2D.tfm")
read_result = sitk.ReadTransform("euler2D.tfm")
assert type(read_result) == type(basic_transform)
library(SimpleITK)
basic_transform <- Euler2DTransform()
basic_transform$SetTranslation(c(2,3))
WriteTransform(basic_transform, 'euler2D.tfm')
read_result = ReadTransform('euler2D.tfm')
stopifnot(read_result$GetName() != basic_transform$GetName())
require 'simpleitk'
basic_transform = Simpleitk::Euler2DTransform.new
trans = Simpleitk::VectorDouble.new
trans << 2.0
trans << 3.0
basic_transform.set_translation(trans)
Simpleitk::write_transform(basic_transform, 'euler2D.tfm')
read_result = Simpleitk::read_transform('euler2D.tfm')
raise "This shouldn't happen." unless basic_transform.class != read_result.class
Euler2DTransform basic_transform
set trans { 2.0 3.0 }
basic_transform SetTranslation $trans
WriteTransform basic_transform "euler2D.tfm"
set read_result [ ReadTransform "euler2D.tfm" ]
if { [basic_transform GetName] == [$read_result GetName] } {
error "This should not happen" 1
}
basic_transform -delete
$read_result -delete
In all languages, except Python, read_result
returns an object of the
generic sitk.Transform()
class and basic_transform
creates a
sitk.Euler2DTransform()
object, but both
represent the same transformation. Although this example only uses a single
SimpleITK transformation, a .tfm file can hold a composite (set of
transformations).