vtkImageReslice origin/direction calculation problem

Sorry to bother you.
I really need some help in vtkImageReslice class!!!

The Problem is : I get the vtkImageData from MR dicom images. I want to get the oblique image form it by given origin and direction;

Here is the part of code:

 vtkSmartPointer<vtkImageData>  m_image_data; 

 int b_dims[3];

 m_image_data->GetDimensions(b_dims); //512, 512, 20

 double b_sp[3];

 m_image_data->GetSpacing(b_sp); //0.7 0.7 6

 double b_center[3];

 m_image_data->GetCenter(b_center);  

 double reslice_matrix[16] = {1, 0, 0, b_center[0], 

                                               0, 0, 1, b_center[1],

                                               0, -1, 0, b_center[2],

                                               0, 0, 0, 1};

vtkNew<vtkMatrix4x4> resliceAxes ;

resliceAxes->DeepCopy(reslice_matrix);

int new_dims[3] = {512, 512, 20};

double new_sp[3] = {b_sp[0], b_sp[1], b_sp[2]};

vtkSmartPointer<vtkImageReslice> reslice = vtkSmartPointer<vtkImageReslice>::New();

reslice->SetInputData(m_image_data);

reslice->SetOutputDimensionality(3);

reslice->SetOutputExtent(0, new_dims[0] - 1, 0, new_dims[1] - 1, 0, new_dims[2] - 1);

reslice->SetOutputSpacing(new_sp[0], new_sp[1], new_sp[2]);

//reslice->SetOutputOrigin(b_center);

reslice->SetResliceAxes(resliceAxes);

reslice->SetInterpolationModeToCubic();

reslice->Update();

The question :

How to calc the origin and directionMatrix of reslice data based on resliceAxes and inputData, outputOrigin ?

  • In many examples, the resliceAxesOrigin is usually set to be image center. if I have b_center to be another position, it seem to the same result?

  • In VTK9.0, imagedata has directionMatrix, when I set image data origin and direction matrix, ( origin is not {0, 0, 0}, directionMatrix is not identity matrix) , alse give me a different reslice data.

Thanks very much!

First, I’d like to thank you for posting your code. That makes it much easier to answer the question.

When you use vtkImageReslice to reformat a volume, the reslice matrix should be constructed so that it transforms the center of the output volume to the center of the input volume. (Actually the reference point doesn’t have to be the center point, but the center point is usually the most convenient).

In homogeneous coordinates with a 4x4 matrix M,

c_input = M * c_output

We already know c_input, and all of M except for the last column (the ResliceAxesOrigin). The problem becomes easier if we separate M into a 3x3 matrix R_axes (the ResliceAxesDirectionCosines) and a 3-vector o_axes (the ResliceAxesOrigin):

c_input = R_axes * c_output + o_axes

We can then solve this for the ResliceAxesOrigin:

o_axes = c_input - R_axes * c_output

Up to this point, everything should be straightforward. But we don’t know c_output yet! So we have to choose constraints so that c_output makes sense. I said “choose”, because there isn’t just one answer, there are many possible answers.

The simplest constraint we can choose is c_output = (0, 0, 0). With this choice, o_axes = c_input. This is why many of the examples set ResliceAxesOrigin to the image center, they do it because it’s easy. Some of those examples make things even simpler by modifying the input image so that c_input is also zero. Then, everything is zero except for the matrix R_axes!

A better constraint is for c_output to be a permutation of c_input. So if c_input = (c_x, c_y, c_z) and we rotate by 90 degrees around z, we can use c_output = (c_y, c_x, c_z). This is a very good constraint for orthogonal reslicing.

For oblique slicing, things are more complicated. One reasonable constraint is to choose the permutation that is closest to the rotation. Another possibility is to use the absolute value of the direction cosines to compute c_output from c_input, since this is the same as permutation if the reslicing is orthogonal.

The take-home message is this: if you want to know what ResliceAxesOrigin to use, then first you must choose a good center for the output.

Also: once you choose the output center, you must set the OutputOrigin. If you don’t, then vtkImageReslice will use convoluted internal logic to “guess” a reasonable value for OutputOrigin – the fact that you didn’t set OutputOrigin is why you kept getting the same result.

reslice->SetOutputOrigin(c_output[0] - new_sp[0]*(new_dims[0] - 1)*0.5,
                         c_output[1] - new_sp[1]*(new_dims[1] - 1)*0.5,
                         c_output[2] - new_sp[2]*(new_dims[2] - 1)*0.5);

Currently, vtkImageReslice ignores the Direction of the vtkImageData. To be safe, you should not use oriented images with vtkImageReslice.

1 Like