OrientImageFilter changes the origin of the image

I tried doing the re-conversion of the RAI image from both the itk::Image Pointer and the saved image on disk [ref ] and it turns out, there are differences when the file is written from the disk

I am able to reproduce this using multiple anisotropic images. I used the code that @mihail.isakov gave with same results (ref).

Thanks for all the help @dzenanz @blowekamp @mihail.isakov

So, the issue is actually in the NIfTI IO class. I tried writing the files using different formats (mha, nrrd, nii, img+hdr) and all formats associated with that class had the same issue (ref). To work around this issue, I have decided to use MHA/NRRD for now.

1 Like

BTW, this issue is present in the VTK format as well (ref).

Yes, you are right, i can reproduce the issue with Nifti IO. Here is test, no image is required to load, is created.

r@deb:~/tmp/test077/build$ ./test077
*** Origin [-100.04, -158.669, -101.794]
Direction
0.999998 0.00174533 0
-0.00174533 0.999998 0
0 0 1

*** Re-opened
Origin [-100.04, -158.669, -101.794]
Direction
0.999998 0.00182698 0
-0.00182698 0.999998 0
0 0 1

#include "itkImage.h"
#include "itkImageFileWriter.h"
#include "itkImageFileReader.h"

int main(int argc, char ** argv)
{
  typedef itk::Image<float, 3> ImageType; 
  typedef itk::ImageFileWriter<ImageType> WriterType;
  typedef itk::ImageFileReader<ImageType> ReaderType;
  {
    ImageType::Pointer image = ImageType::New();
    ImageType::IndexType index;
    ImageType::SizeType size;
    ImageType::RegionType region;
    ImageType::SpacingType spacing;
    ImageType::PointType origin;
    ImageType::DirectionType direction;
    index.Fill(0);
    size[0] = 192;
    size[1] = 256;
    size[2] = 192;
    spacing[0] = 0.976562;
    spacing[1] = 0.976562;
    spacing[2] = 1;
    origin[0] = -100.04;
    origin[1] = -158.669;
    origin[2] = -101.794;
    direction(0,0) = 0.999998;
    direction(0,1) = 0.00174533;
    direction(0,2) = 0;
    direction(1,0) = -0.00174533;
    direction(1,1) = 0.999998;
    direction(1,2) = 0;
    direction(2,0) = 0;
    direction(2,1) = 0;
    direction(2,2) = 1;
    region.SetIndex(index);
    region.SetSize(size);
    try
    {
      image->SetRegions(region);
      image->Allocate();
      image->SetOrigin(origin);
      image->SetSpacing(spacing);
      image->SetDirection(direction);
    }
    catch (itk::ExceptionObject & ex)
    {
      std::cout << ex.GetDescription() << std::endl;
      return 1;
    }
    std::cout << "*** Origin " << image->GetOrigin() << std::endl;
    std::cout << "Direction\n" << image->GetDirection() << std::endl;
    WriterType::Pointer writer = WriterType::New();
    writer->SetInput(image);
    writer->SetFileName("output.nii.gz"); // MHA is OK
    try
    {
      writer->Write();
    }
    catch (itk::ExceptionObject & ex)
    {
      std::cout << ex.GetDescription() << std::endl;
      return 1;
    }
  }

  {
    ImageType::Pointer reopened;
    ReaderType::Pointer reader = ReaderType::New();
    reader->SetFileName("output.nii.gz"); // MHA is OK
    try
    {
      reader->Update();
      reopened = reader->GetOutput();
    }
    catch (itk::ExceptionObject & ex)
    {
      std::cout << ex.GetDescription() << std::endl;
      return 1;
    }
    std::cout << "*** Re-opened\nOrigin " << reopened->GetOrigin() << std::endl;
    std::cout << "Direction\n" << reopened->GetDirection() << std::endl;
  }
  return 0;
}

I didn’t looked closer, but could not reproduce with open/write Nifti images, may be, not sure, once written as Nifti image the image has matrix somehow compatible with computations, but not every matrix, the image above is valid, BTW, there should be no reason for mistake, IMHO. Don’t know, but there is something, there is also the issue about "round trip problems writing some DICOM files to Nifti and back, it is the same, may be.

P.S. As @blowekamp mentioned, orientation filter is absolutely OK, i have played with this testand geometry survived 500 random re-orientation. I think it is good news, IMHO.

1 Like

I created a new issue to track this. I also closed the old one.

3 Likes