Correcting the Gantry Tilt in CT scans

Hi I am using vtkDicomReader to read the scans and then using vtkDICOMCTRectifier for gantry tilt correction. Here is my code:

rectify = vtkDICOMCTRectifier()

I am passing the output of the rectifier to vtkImageMapToColors.
The gantry tilt is not corrected from the above code. Is there anything else I have to do?

It’s possibly just a misunderstanding of what vtkDICOMCTRectifier does. It actually keeps the same slice planes as the input, it just shifts the bounds of each slice plane so that boundary of the volume is rectangular:

So the result is a rectangular volume, and the volume is rotated rather than sheared.

An alternative way of rectifying a volume (which is not what vtkDICOMCTRectifier does) is to reslice the image so that all of the planes are vertical. But this kind of oblique reslicing always causes a small amount of image degradation:

Probably the easiest way to check if the rectification works is to look at a sagittal view to see if there is distortion.

Hi David,

Thanks for the prompt reply and a detailed explanation.
The above code is not correcting the shear.

This is how the sagittal view looks after the rectification.

Is it right to pass the rectifier output to the vtk rendering pipeline or should i transform/reslice the volume with the transformation matrix from rectifier?

Yes, that’s definitely not rectified! Can you send the PatientMatrix from the reader? And even better, can you send the ImagePositionPatient and ImageOrientationPatient from at least two of the images?

The rectifier output can be sent directly to the rendering pipeline, no further transformations should be necessary. I’ve tested it on several images.

You might also try the approach used in Slicer’s dicom importer where we create a nonlinear transform to correct for gantry tilt. This preserves the original image data so you can later resample it at arbitrary resolution if you choose. This approach also handles the not uncommon issue of irregular slice spacing in CT (created by changing the table speed) or even gaps (which may be done on purpose to minimize radiation exposure or could be due to missing slices).

Patient Matrix:

1 -0 0 -125
0 -0.963631 -0.267238 137.383
0 0.267238 -0.963631 55.521
0 0 0 1

Slice: 100:
Image Position Patient: -125.000-103.054\21.020
Image Orientation Patient: 1.000000\0.000000\0.000000\0.000000\0.963630-0.267238

Slice: 189:
Image Position Patient: -125.000-103.054\78.744
Image Orientation Patient: 1.000000\0.000000\0.000000\0.000000\0.963630-0.267238

Thanks Steve. Will try this out as well.

Thanks, those all look correct.

Are you sure that you are calling Update() on the reader before the following?


The PatientMatrix will be identity until either Update() or UpdateInformation() is called. I’m just checking because that would be the simplest reason for it to fail.

yup, i am calling reader.Update()

Thanks for the reply. If you built vtk-dicom from source, one thing you can run as a test is the “TestDICOMDisplay” example. Its source is in the Examples directory, and it is built if BUILD_DICOM_EXAMPLES and BUILD_EXAMPLES are set during configuration. It requires all the dicom files as input:

TestDICOMDisplay /path/to/files/*.dcm

This example automatically applies tilt correction to any input CT files.

Edit: Also, you can try changing the interpolation used by the rectifier. When I try them locally on one of my own tilted data sets, all four methods work:


The default is WindowedSinc.

Hi David,

Changing the interpolation modes didnt help.

I have to build vtk from source with examples to test with “TestDICOMDisplay”. Apart from this is there anything else i can try?

Which vtk binary package are you using? I can try using the same one to see if I can reproduce the problem.

I built it from source with gdcm and vtk-dicom enabled. Cloned it from kitware github repo.

In order to move forward from here, it seems the only options are for you to send me your code, so that I can test it locally, or for you to build TestDICOMDisplay, to see if it works on your data set.

i can send you the scans, will that be enough?

if it works for you then there’s something I am doing wrong, and then I can send you the code. is that ok?

Yes, if you can send a link to your data and/or code vi email (david.gobbi at gmail dot com) or via this messageboard, then I can take a look.

Hi David,

I have mailed you the scans and the code snippet.

Thanks. I tested the image with the TestDICOMDisplay example, and the rectification worked properly. Here’s a screenshot, the sagittal view is in the lower right corner:

I’m not able to run the code that you sent, because it isn’t a complete program. But the part of the code where it does the rectification looks fine. Here is the similar code from TestDICOMDisplay.cxx, for comparison:

  vtkSmartPointer<vtkDICOMCTRectifier> rect;
  if (meta->Get(DC::Modality).Matches("CT"))
    rect = vtkSmartPointer<vtkDICOMCTRectifier>::New();
    portToDisplay = rect->GetOutputPort();

So I’m not sure what the problem is. Is it possible that your display pipeline is actually displaying the wrong image? Or maybe the display pipeline is using the PatientMatrix in a way that causes the rectification to be reversed? I notice that you never call rectify.GetRectifiedMatrix(). If you want to use the matrix to set the orientation of the image after rectification, it’s necessary to use the RectifiedMatrix (since the original PatientMatrix no longer applies, once the rectification has been done).

I am just passing the rectifier output to vtkImageMapToColors. I am changing the camera viewup vector so that the views are displayed in correct orientation, but that should not affect the rectification right?.