Direction of images not matching

Hi,

I’ve been using a dataset of registered brain MRI’s (T1, T2, FLAIR and T1ce) as input for a CNN implemented in MONAI. The different modalities have been registered using BRAINSFIT. After registration, segmentations have been created on these images.
Now for part of the dataset I have the issue that the directions of some modalities and of some segmentation files do not fully correspond (which is necessary for them to be stacked as an input for the CNN). For example, for one subject I get:

Direction of T1CE:
[[ 0.99363196 -0.08103074 -0.07829134]
[-0.05990832 -0.96842784 0.24198869]
[ 0.09542805 0.23575737 0.96711527]]
and direction of SEG:
[[ 0.99363197 -0.08103075 -0.07829135]
[-0.05990831 -0.96842784 0.24198867]
[ 0.09542804 0.23575738 0.96711527]]

We can see that the values are very close together, yet not exactly the same.
I’ve tried correcting this by using

seg.SetDirection(t1ce.GetDirection())

and overwriting the segmentation file, but when I check the directions afterwards, they remain unchanged.
What could be going on here?

Thanks in advance!

Hello @sdesutter,

What file format are you using to the save the image? Formats like mhd write a text header file which includes the image meta-data. The precision of what is written may be different from what you have in memory. I don’t think this is what is happening here, but I may be wrong. An old and resolved issue which dealt with precision discrepancy problems may be relevant, depends on which ITK/SimpleITK version is being used.

More importantly, the issue here is the concept of equality between floating point numbers. The two direction cosine matrices are considered equivalent up to a given threshold, same way you would compare any two floating numbers for equality.

In SimpleITK the two matrices provided in the example are considered equivalent. Below is code which illustrates how to check if two images have the same metadata up to the threshold used by SimpleITK (origin, spacing, direction cosine matrix):

import SimpleITK as sitk


def equal_metadata(image1, image2):
    # Create smallest possible images with same metadata as originals and cast to
    # same pixel type so that the addition operation is always valid. Any exception
    # is a result of inconsistent metadata.
    image1_meta = sitk.Cast(sitk.Extract(image1, [1]*image1.GetDimension()), sitk.sitkUInt8)
    image2_meta = sitk.Cast(sitk.Extract(image2, [1]*image2.GetDimension()), sitk.sitkUInt8)
    try:
        image1_meta + image2_meta
        return True
    except Exception as e:
        # Uncomment next line to see what is the discrepancy:
        # print("not equal metadata: " + str(e))
        return False


image1 = sitk.Image([10, 20, 30], sitk.sitkFloat32)
image1.SetDirection(
    [
        0.99363196,
        -0.08103074,
        -0.07829134,
        -0.05990832,
        -0.96842784,
        0.24198869,
        0.09542805,
        0.23575737,
        0.96711527,
    ]
)

image2 = sitk.Image([10, 20, 30], sitk.sitkUInt8)
image2_dir = [
    0.99363197,
    -0.08103075,
    -0.07829135,
    -0.05990831,
    -0.96842784,
    0.24198867,
    0.09542804,
    0.23575738,
    0.96711527,
]
image2.SetDirection(image2_dir)

if equal_metadata(image1, image2):
    print("1: equal metadata (up to SimpleITK eps)")
else:
    print("1: not equal metadata (up to SimpleITK eps)")
    
image2_dir[0] = 0.99363
image2.SetDirection(image2_dir)
if equal_metadata(image1, image2):
    print("2: equal metadata (up to SimpleITK eps)")
else:
    print("2: not equal metadata (up to SimpleITK eps)")
1 Like