mlavik1 / UnityVolumeRendering

Volume rendering, implemented in Unity3D. Want to support the project? Donate a small sum to Save The Children(https://www.savethechildren.net/) or another charity, and send me a message, and I will be greatly motivated!
https://fosstodon.org/@unityvolrend
MIT License
458 stars 129 forks source link

Replace ImportUtilsInternal.ConvertLPSToUnityCoordinateSpace with SimpleITK.DICOMOrient #244

Closed MichaelOvens closed 7 months ago

MichaelOvens commented 7 months ago

DICOM datasets are conventionally structured in a left posterior superior (LPS) coordinate space. This means that the X axis increases as it moves leftwards; the Y axis increases as it moves backwards; and the Z axis increases as it moves upwards. Directions are defined in patient coordinate space (PCS), so left refers to the patients left, anterior the patient's anterior, superior the patient's superior.

image _Image from https://www.slicer.org/wiki/Coordinate_systems_

Unity, on the other hand, uses a right superior anterior coordinate system. Assuming we want to remain in PCS (ie pretend the patient is standing upright rather than lying down) then the Unity coordinate system should look like this:

image

The most significant difference between these two coordinate systems is that LPS is a right-handed system while Unity is a left-handed system. This means that, leaving aside any rotation errors, importing DICOM images into Unity without any kind of conversion will result in a volume that's mirror on the X-axis.

UVR currently accounts for this by applying a manual post-import conversion function (ImporterUtilsInternal.ConvertLPSToUnityCoordinateSpace) that multiplies the X-axis scale by -1 and applies a 270 degree rotation around the X axis, but this doesn't actually convert the volume into the desired space, and it doesn't do it consistently across different file types. To test this, I took an MRI scan of a volunteer's right foot which was exported as a DICOM dataset, then converted it to NRRD, NIFTI, and a JPEG image sequence before importing all of these formats into UVR.

DICOM NRRD NIFTI JPEG
image image image image

Although DICOM and NIFTI imported in the same orientation, it's the incorrect orientation - in a PCS, the foot should be upright and the toes pointing forwards (z-positive). NRRD imported upright, but pointing backwards. The JPEG sequence came out inverted on the X axis, suggesting it shouldn't have been inverted.

SimpleITK has a function to allow converting datasets into different coordinate systems - SimpleITK.DICOMOrient - before we load them into a Unity Texture3D. Using this function helps ensure that files are loaded into the correct coordinate space without having to apply scene-level rotations or scale transforms. Using the changes made in this PR (removing the existing conversion and replacing it with the SimpleITK function), we get the following outputs:

DICOM NRRD NIFTI JPEG
image image image image

Note that although the foot is upside down, it's no longer mirrored on the X axis. There might be grounds for applying a rotation to it, but there's only so much that can be done for images sequences because they don't contain any embedded orientation data, so my inclination is to import them as raw as possible.

I've tested the import on a second dataset and confirmed that DICOM, NRRD, and NIFTI imports consistently (image sequence wouldn't load any data, possibly because it's a very faint dataset), but I can't share those images as they're of a patient rather than a volunteer.

mlavik1 commented 7 months ago

Thanks a lot for this PR @MichaelOvens , and for taking the time to write such a detailed description! This is really great :)