[vtk-developers] vtkNIFTIImageReader coordinates

padraig padraig.looney at gmail.com
Sun Nov 13 11:50:16 EST 2016


Hi David,


I am still confused by this. Volumes that ITK tells me have the same 
bounds, VTK displays in Paraview as not having the same bounds.

Consider this header from

vtkNIFTIImageHeader (0x221e6b0)
   Debug: Off
   Modified Time: 85
   Reference Count: 1
   Registered Events: (none)
   DimInfo: 0x0
   Dim: 3 224 153 52 1 1 1 1
   PixDim: 1 0.9195 1.40018 2.89048 0 0 0 0
   VoxOffset:352
   IntentP1: 0
   IntentP2: 0
   IntentP3: 0
   IntentCode: 0
   DataType: 2
   BitPix: 8
   SliceStart: 0
   SclSlope: 1
   SclInter: 0
   SliceEnd: 0
   SliceCode: 0
   XYZTUnits: 0x2
   CalMax: 0
   CalMin: 0
   SliceDuration: 0
   TOffset: 0
   Descrip: ""
   AuxFile: ""
   QFormCode: 2
   SFormCode: 1
   QuaternB: 0
   QuaternC: 0
   QuaternD: 1
   QOffsetX: 102.536
   QOffsetY: 106.413
   QOffsetZ: 30.1491
   SRowX: -0.9195 0 0 102.536
   SRowY: 0 -1.40018 0 106.413
   SRowZ: 0 0 2.89048 30.1491
   IntentName: ""
   Magic: "n+1"

That is the same as the affine from nibabel


array([[  -0.91949999,    0.        ,    0.        , 102.53600311],
        [   0.        ,   -1.40017998,    0.        , 106.41300201],
        [   0.        ,    0.        ,    2.89048004, 30.14909935],
        [   0.        ,    0.        ,    0.        ,    1. ]])


If you look at the SForm matrix below shouldn't the bounds be

X: (224-1)*-0.9195 + 102.536 = -102.51249999999999

Y: (153-1)*-1.40018 + 106.413 =--106.41436

Z: (52-1)*2.89048 + 30.1491 = 177.56358


In ITK I have checked the physical coordinates of the image and found 
the bounds to be, as expected from the above,

[-102.536, -106.413, 30.1491][102.512, 106.414, 177.564]

In VTK I have checked the centre and origin with

     vtkNew<vtkNIFTIImageReader> niiReader;
     niiReader->SetFileName(str);
     niiReader->Update();
     int size[3];
     double center[3], spacing[3], bounds[6];
     niiReader->GetOutput()->GetDimensions(size);
     niiReader->GetOutput()->GetCenter(center);
     niiReader->GetOutput()->GetBounds(bounds);
     std::vector<double> bounds_vec(&bounds[0],&bounds[6]);
     std::cout << bounds[0] << " " << bounds[1] << " " << bounds[2]  << 
" " << bounds[3] << " " << bounds[4] << " " << bounds[5] << std::endl;
     niiReader->GetOutput()->GetSpacing(spacing);
     double center1[3] = { center[0], center[1], center[2] };
     double center2[3] = { center[0], center[1], center[2] };
     std::cout << center[0] << " " << center[1] << " " << center[2] << 
std::endl;
     std::cout << size[0] << " " << size[1] << " " << size[2] << std::endl;

and get

0 205.048 0 212.827 0 147.414
102.524 106.414 73.7072
224 153 52

On 12/11/16 15:39, David Gobbi wrote:
> Hi Padraig,
>
> The "direction" or "orientation" is the 3x3 portion of the 4x4 matrix, 
> after dividing out the scale.
>
> So if ITK is giving a direction like the following, it means that ITK 
> allows the direction to include a mirror-flip (in this case, it's a 
> flip along the z-axis):
>
> 1 0 0
> 0 1 0
> 0 0 -1
>
> The vtkNIFTIImageReader doesn't allow a mirror flip in the 
> QFormMatrix, so instead it re-orders the nifti slices in memory to 
> undo the flip. When it does this, it also has to adjust the 4th column 
> of the QFormMatrix since the 4th column now indicates the position of 
> the last slice in the file, instead of the first slice in the file.  
> The difference in position between the first slice and the last slice 
> is (n - 1)*sz, where n is the number of slices and sz is the slice 
> spacing.  For your image, we can add (n - 1)*sz to -117.265 in order 
> to get 30.149:
>
>     -117.265 + (52 - 1)*2.89048 = 30.149
>
> This accounts for the discrepancy.
>
>  - David
>
> On Sat, Nov 12, 2016 at 7:42 AM, padraig <padraig.looney at gmail.com 
> <mailto:padraig.looney at gmail.com>> wrote:
>
>     Hi David,
>
>
>     vtkNIFTIImageHeader (0x3346680)
>       Debug: Off
>       Modified Time: 85
>       Reference Count: 1
>       Registered Events: (none)
>       DimInfo: 0x0
>       Dim: 3 224 153 52 1 1 1 1
>       PixDim: -1 0.9195 1.40018 2.89048 0 0 0 0
>       VoxOffset:352
>       IntentP1: 0
>       IntentP2: 0
>       IntentP3: 0
>       IntentCode: 0
>       DataType: 2
>       BitPix: 8
>       SliceStart: 0
>       SclSlope: 1
>       SclInter: 0
>       SliceEnd: 0
>       SliceCode: 0
>       XYZTUnits: 0x2
>       CalMax: 0
>       CalMin: 0
>       SliceDuration: 0
>       TOffset: 0
>       Descrip: ""
>       AuxFile: ""
>       QFormCode: 2
>       SFormCode: 1
>       QuaternB: 0
>       QuaternC: 0
>       QuaternD: 1
>       QOffsetX: 102.536
>       QOffsetY: 106.413
>       QOffsetZ: 30.1491
>       SRowX: -0.9195 0 -0 102.536
>       SRowY: 0 -1.40018 -0 106.413
>       SRowZ: 0 0 -2.89048 30.1491
>       IntentName: ""
>       Magic: "n+1"
>
>     The direction in ITK is
>
>
>     1 0 0
>     0 1 0
>     0 0 -1
>
>     I don't know how to see the direction in nibabel
>
>
>     On 12/11/16 14:10, David Gobbi wrote:
>>     Hi Padraig,
>>
>>     Can you show us the raw qform and sform fields from the NIFTI
>>     header itself? In VTK, you can do this as follows:
>>
>>     >>> print(reader.GetNIFTIHeader())
>>
>>     The difference you see between nibabel, ITK, and VTK has to do
>>     with differences in the way these packages deal with the pixdim
>>     and the qfac of the nifti file.  If you print the Direction from
>>     the ITK image you might find that it differs from nibabel, too.
>>
>>     For VTK, you can read all the gory details here:
>>
>>     http://gitlab.kitware.com/vtk/vtk/blob/v7.0.0/IO/Image/vtkNIFTIImageReader.cxx#L738
>>     <http://gitlab.kitware.com/vtk/vtk/blob/v7.0.0/IO/Image/vtkNIFTIImageReader.cxx#L738>
>>
>>      - David
>>
>>
>>     On Sat, Nov 12, 2016 at 6:10 AM, padraig
>>     <padraig.looney at gmail.com <mailto:padraig.looney at gmail.com>> wrote:
>>
>>         I have noticed some inconsistencies in how NIFTI images are
>>         handled in VTK, ITK, and NiBabel. ITK and NiBabel are in
>>         agreement with each other and differ with VTK on the position
>>         of the volume. The VTK output for a file is below.
>>
>>         vtkNIFTIImageReader (0x1de67d0)
>>           Debug: Off
>>           Modified Time: 91
>>           Reference Count: 2
>>           Registered Events: (none)
>>           Executive: 0x1de7720
>>           ErrorCode: Success
>>           Information: 0x1de6ad0
>>           AbortExecute: Off
>>           Progress: 1
>>           Progress Text: (None)
>>           FileName:
>>         /home/padraig/Desktop/59674/Seeding/I0000003_59674_sn.nii
>>           FileNames: 0
>>           FilePrefix: (none)
>>           FilePattern: %s.%d
>>           FileNameSliceOffset: 0
>>           FileNameSliceSpacing: 1
>>           DataScalarType: unsigned char
>>           NumberOfScalarComponents: 1
>>           File Dimensionality: 3
>>           File Lower Left: On
>>           Swap Bytes: Off
>>           DataIncrements: (1, 1)
>>           DataExtent: (0, 223, 0, 152, 0, 51)
>>           DataSpacing: (0.9195, 1.40018, 2.89048)
>>           DataOrigin: (0, 0, 0)
>>           HeaderSize: 352
>>           Internal File Name: (none)
>>           TimeAsVector: Off
>>           TimeDimension: 1
>>           TimeSpacing: 1
>>           RescaleSlope: 1
>>           RescaleIntercept: 0
>>           QFac: -1
>>           QFormMatrix: -1 0 0 102.536 0 -1 0 106.413 0 0 1 -117.265 0
>>         0 0 1
>>           SFormMatrix: -1 0 -0 102.536 0 -1 -0 106.413 0 0 1 -117.265
>>         0 0 0 1
>>           NIFTIHeader:
>>           PlanarRGB: Off
>>
>>         the qform given by nibabel is
>>
>>         >>> ni_ob.get_qform()
>>         array([[  -0.91949999,    0. ,    0.        ,  102.53600311],
>>                [   0.        , -1.40017998,    0.        ,
>>         106.41300201],
>>                [   0.        ,    0. ,    2.89048004,   30.14909935],
>>                [   0.        ,    0. ,    0.        ,    1. ]])
>>
>>
>>         ITK has the origin at
>>
>>         [-102.536, -106.413, 30.1491]
>>
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtk-developers/attachments/20161113/69b55a56/attachment.html>


More information about the vtk-developers mailing list