[ITK] Nifti Image to World Orientation
Matt McCormick
matt.mccormick at kitware.com
Fri Apr 15 11:30:10 EDT 2016
Hi Nicolas,
Slicer modifies the coordinate system from ITK as described here:
https://www.slicer.org/slicerWiki/index.php/Coordinate_systems
HTH,
Matt
On Fri, Apr 15, 2016 at 7:10 AM, Nicolas Rannou <nicolas at eunate.ch> wrote:
> Hi all,
>
> Apologizes if it is another duplicate but I couldn’t find any
> relevant/recent information about my issue.
>
> Is it possible to display image to world transform for an image in ITK?
>
> I am trying to figure out how ITK handles the orientation for this Nifti
> file:
> https://drive.google.com/open?id=0B2-PspfnvPNgY1R2SFFTd3YtaGM
>
> The image to world transform I get if I compute it “manually" from the
> header or run it in Nibabel does not match Slicer's (which is based on ITK)
> [1]. Also, if I convert this Nifiti file to NRRD in ITK, the orientation
> returned by the NRRD header matches Slicer but not Nibabel.
>
> SLICER:
> -0.859375 0 0 49.8438
> 0 -0.859375 0 -67.8906
> 0 0 0.859375 -53.7109
> 0 0 0 1
>
> NIBABEL:
> array([[ -0.859375 , 0. , 0. , 49.84375 ],
> [ 0. , 0.859375 , 0. , -67.890625 ],
> [ 0. , 0. , 0.859375 , -53.7109375],
> [ 0. , 0. , 0. , 1. ]])
>
>
> NRRD HEADER:
> NRRD0004
> 2 # Complete NRRD file format specification at:
> 3 # http://teem.sourceforge.net/nrrd/format.html
> 4 type: float
> 5 dimension: 3
> 6 space: left-posterior-superior
> 7 sizes: 117 159 126
> 8 space directions: (0.859375,0,0) (0,0.859375,0) (0,0,0.859375)
> 9 kinds: domain domain domain
> 10 endian: little
> 11 encoding: raw
> 12 space origin: (-49.84375,67.890625,-53.7109375)
>
>
> I understand the RAS/LPS differences but what doesn’t makes sense to me are
> the space directions in the NRRD header: -0.85 on the second vector would
> make sense to me:
> (0.859375,0,0) (0,-0.859375,0) (0,0,0.859375)
> I would also expect slicer [0][0] and [1][1] indices to have opposite signs.
> (like Nibabel)
> -0.859375 0 0 49.8438
> 0 0.859375 0 -67.8906
> 0 0 0.859375 -53.7109
> 0 0 0 1
>
>
> I couldn’t track down where this modification happens in ITK.
> Does ITK do any kind of correction to adjust the orientation somehow?
>
>
> As a test, I convert my Nifti to NRRD [2] and run the program step by step.
>
> In the Nifti parser, one of the last steps is to set the “Direction” to:
> (NiftiImageIO::SetImageIOOrientationFromNIfTI - Around line 1700)
> Direction 0: [1,-0,0]
> Direction 1: [-0,-1,0]
> Direction 2: [0,0,1]
>
> Then, when the NRRD parser tries fo fetch the direction it becomes:
> (NrrdImageIO::Write - Around line 945)
> Direction 0 [1,0,0]
> Direction 1 [0,1,0]
> Direction 2 [0,0,1]
>
> I couldn’t track down where this is happening or if that even makes sense.
>
> Best,
> Nicolas
>
> [1]
> -------------------------------------------------------
> nifti_1_header :
> sizeof_hdr = 348
> data_type[10] = 0x 0 0 0 0 0 0 0 0 0 0
> db_name[18] = 0x 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
> extents = 0
> session_error = 0
> regular = 0x72
> dim_info = 0x0
> dim[8] = 4 117 159 126 15 1 1 1
> intent_p1 = 0.000000
> intent_p2 = 0.000000
> intent_p3 = 0.000000
> intent_code = NIFTI_INTENT_NONE
> datatype = 16
> bitpix = 32
> slice_start = 0
> pixdim[8] = -1.000000 0.859375 0.859375 0.859375
> 1.000000 0.000000 0.000000 0.000000
> vox_offset = 352.000000
> scl_slope = 1.000000
> scl_inter = 0.000000
> slice_end = 0
> slice_code = 0
> xyzt_units = 0x12
> cal_max = 0.000000
> cal_min = 0.000000
> slice_duration = 0.000000
> toffset = 0.000000
> glmax = 0
> glmin = 0
> descrip = ''
> aux_file = ''
> qform_code = 1
> sform_code = 0
> quatern_b = 0.000000
> quatern_c = 1.000000
> quatern_d = 0.000000
> qoffset_x = 49.843750
> qoffset_y = -67.890625
> qoffset_z = -53.710938
> srow_x[4] = 0.000000, 0.000000, 0.000000, 0.000000
> srow_y[4] = 0.000000, 0.000000, 0.000000, 0.000000
> srow_z[4] = 0.000000, 0.000000, 0.000000, 0.000000
> intent_name = ''
> magic = 'n+1'
> ———————————————————————————
>
>
> SLICER
>
>>>> import slicer
>>>> vol = slicer.util.getNode('template_T2.nii')
>>>> IJKToRASMat = vtk.vtkMatrix4x4()
>>>> vol.GetIJKToRASMatrix(IJKToRASMat);
>>>> print(IJKToRASMat)
> vtkMatrix4x4 (0x140294910)
> Debug: Off
> Modified Time: 980729
> Reference Count: 1
> Registered Events: (none)
> Elements:
> -0.859375 0 0 49.8438
> 0 -0.859375 0 -67.8906
> 0 0 0.859375 -53.7109
> 0 0 0 1
>
> NIBABEL
>
> In [2]: example_filename =
> '/Users/nico/work/gitroot/ami/data/nifti/FetalAtlas/template_T2.nii.gz'
>
> In [3]: import nibabel as nib
>
> In [4]: img = nib.load(example_filename)
>
> In [5]: img.shape
> Out[5]: (117, 159, 126, 15)
>
> In [6]: img.affine
> Out[6]:
> array([[ -0.859375 , 0. , 0. , 49.84375 ],
> [ 0. , 0.859375 , 0. , -67.890625 ],
> [ 0. , 0. , 0.859375 , -53.7109375],
> [ 0. , 0. , 0. , 1. ]])
>
> [2]
> typedef itk::Image<float, 3> InputImageType;
> typedef itk::Image<float, 3> OutputImageType;
>
> typedef itk::ImageFileReader<InputImageType> ReaderType;
> typedef itk::ImageFileWriter<OutputImageType> WriterType;
>
> ReaderType::Pointer reader = ReaderType::New();
> WriterType::Pointer writer = WriterType::New();
>
> reader->SetFileName(
> "/Users/nico/work/gitroot/data/nifti/fetalatlas_brain/t2/template_T2.nii.gz"
> );
>
> writer->SetFileName( "test.nrrd" );
> writer->SetInput( reader->GetOutput() );
> writer->Update();
>
>
>
>
> [3]
>
>
> _______________________________________________
> Community mailing list
> Community at itk.org
> http://public.kitware.com/mailman/listinfo/community
>
More information about the Community
mailing list