Reslice of ImageData and glyph3D arrows

Hi everyone,

I got a issue with my VTK pipeline but i don’t understand what did i do wrong.
Currently I want to display an image of a 3D volume and on this image I want some 3D glyph arrows.

But when I display it, any arrows aren’t oriented …

Here my pipeline :

imageVectorMem = vtkSmartPointer<vtkImageData>::New();

imageResliceMem =	vtkSmartPointer<vtkImageReslice>::New();
imageResliceMem->SetInputData(imageVectorMem);
imageResliceMem->SetOutputDimensionality(2);

arrowSourceMem = vtkSmartPointer<vtkArrowSource>::New();

glyphFilterMem = vtkSmartPointer<vtkGlyph3D>::New();
glyphFilterMem->SetSourceConnection(arrowSourceMem->GetOutputPort());
glyphFilterMem->SetInputConnection(imageResliceMem->GetOutputPort());
glyphFilterMem->SetVectorModeToUseVector(); 
glyphFilterMem->OrientOn(); 
glyphFilterMem->SetScaleModeToDataScalingOn(); // seems not mandatory
	
vectorMapperMem = vtkSmartPointer<vtkPolyDataMapper>::New();
vectorMapperMem->SetInputConnection(glyphFilterMem->GetOutputPort());

actorMem = vtkSmartPointer<vtkActor>::New();
actorMem->SetMapper(vectorMapperMem);

And when I don’t go throught the vtkImageReslice part it work but i got all my arrow of the volume displayed.

Here my pipeline : (without the reslice part)

imageVectorMem = vtkSmartPointer<vtkImageData>::New();

arrowSourceMem = vtkSmartPointer<vtkArrowSource>::New();

glyphFilterMem = vtkSmartPointer<vtkGlyph3D>::New();
glyphFilterMem->SetSourceConnection(arrowSourceMem->GetOutputPort());
glyphFilterMem->SetInputData(imageVectorMem);
glyphFilterMem->SetVectorModeToUseVector(); 
glyphFilterMem->OrientOn(); 
glyphFilterMem->SetScaleModeToDataScalingOn(); // seems not mandatory
	
vectorMapperMem = vtkSmartPointer<vtkPolyDataMapper>::New();
vectorMapperMem->SetInputConnection(glyphFilterMem->GetOutputPort());

actorMem = vtkSmartPointer<vtkActor>::New();
actorMem->SetMapper(vectorMapperMem);

Thank for any help

Hi Louis,

Can you can add backticks to format your code blocks? E.g.:

```
x = vtkSmartPointer<vtkObject>::New();
```

More importantly, if you don’t do this, then bits of code go missing, e.g.:

x = vtkSmartPointer::New();

I tried to read your code, but I don’t know what classes you are instantiating!

David

Done.

Sorry this is my first time on a forum.

If your imageVectorMem data set has vectors and normals, they will be ignored by vtkImageReslice. It only works on scalar data. You might have to try using vtkProbeFilter instead.

Ok I will try it.

But it seems that the vtkProbeFilter is complex to use, so if you already have an idea how to use it in my pipeline it would be great.

Thanks for your fast replies

I try it since yesterday but it doesn’t work. I guess I don’t use it in a good way.

Could you detail more your solution ?

I don’t see where I have to integrate it and how to use it.

Louis

There are some vtkProbeFilter examples here. The new vtkResampleToImage filter might be easier to use (it is designed to output vtkImageData, and it uses vtkProbeFilter internally).

But if you only need to extract existing slices (rather than generating oblique slices), then vtkExtractVOI might be enough: https://lorensen.github.io/VTKExamples/site/Cxx/ImageData/ExtractVOI/

What I want is to be able to see my vectors, and to be able to change the slice of my volume displayed. And for this I have a matrix 4x4 to set the orientation and the position of my slice displayed.

Seems that the vtkProbeFilter doesn’t work with me …

imageProbeFilterMem = vtkSmartPointer<vtkProbeFilter>::New();
imageProbeFilterMem->SetInputData(imageVectorMem);
imageProbeFilterMem->SetSourceData(imageResliceMem->GetOutput());

The probe filter works the other way around: the “Source” has the attributes you want (the vectors), and the “Input” has the point grid to use for the output. But I’ve been thinking, and the probe filter is probably not the best solution for you, since you already have something that almost works with vtkImageReslice (and ImageReslice is also much faster than Probe, since it is designed specifically for image data).

I remembered some old code that I wrote that does something similar to what you want. In my case, I had tensor values for every voxel in my image volume and I displayed them with vtkImageReslice and vtkTensorGlyph. The code is here and the resulting image looked like this:

The trick was to create a temporary image where the “Tensors” were moved to the “Scalars” so that vtkImageReslice would reslice them. Something like the following:

# make a new data set where tensors are scalars
vtkSmartPointer<vtkImageData> tensorsAsScalars =
  vtkSmartPointer<vtkImageData>::New();
tensorsAsScalars->CopyStructure(tensorData);
tensorsAsScalars->GetPointData()->SetScalars(
  tensorData->GetPointData()->GetTensors());

# reslice works because the data is stored as Scalars
tensorReslice->SetInputData(tensorsAsScalars);

# put the scalar data back into "Tensors" for use by vtkTensorGlyph
vtkSmartPointer<vtkImageData> tensorsData2 =
  vtkSmartPointer<vtkImageData>::New();
tensorsData2->CopyStructure(tensorReslice->GetOutput());
tensorsData2->GetPointData()->SetTensors(
  tensorReslice->GetOutput()->GetPointData()->GetScalars());

In my case, I wasn’t applying any rotation when I was reslicing, so I didn’t have to rotate the tensors after resampling them.

Thank for your replies !

It seems it still does not work … this time I got nothing displayed as if my glyph does not have any input.

Not worries for the rotation, I already have a case where it work, so I just have to fix the display of my vector in arrows

Here my new pipeline, tell me if I do something wrong that I do not see :

imageVectorMem = vtkSmartPointer<vtkImageData>::New();

imageVectorMem2 = vtkSmartPointer<vtkImageData>::New();
imageVectorMem2->CopyStructure(imageVectorMem);
imageVectorMem2->GetPointData()->SetScalars(imageVectorMem->GetPointData()->GetVectors());

imageResliceMem = vtkSmartPointer<vtkImageReslice>::New();
imageResliceMem->SetInputData(imageVectorMem2);
imageResliceMem->SetOutputDimensionality(2);
//imageResliceMem->SetInterpolationMode(true ? VTK_RESLICE_LINEAR : VTK_RESLICE_NEAREST);
//imageResliceMem->SetInterpolationMode(true);

imageVectorSliceMem = vtkSmartPointer<vtkImageData>::New();
imageVectorSliceMem->CopyStructure(imageResliceMem->GetOutput());
imageVectorSliceMem->GetPointData()->SetVectors(imageResliceMem->GetOutput()->GetPointData()->GetScalars());
//imageVectorSliceMem->GetPointData()->SetActiveVectors("ImageScalars");
	
arrowSourceMem = vtkSmartPointer<vtkArrowSource>::New();
glyphFilterMem = vtkSmartPointer<vtkGlyph3D>::New();
glyphFilterMem->SetSourceConnection(arrowSourceMem->GetOutputPort());
glyphFilterMem->SetInputData(imageVectorSliceMem);
glyphFilterMem->SetVectorModeToUseVector(); 
glyphFilterMem->OrientOn(); 
  
vectorMapperMem = vtkSmartPointer<vtkPolyDataMapper>::New();
vectorMapperMem->SetInputConnection(glyphFilterMem->GetOutputPort());

actorMem = vtkSmartPointer<vtkActor>::New();
actorMem->SetMapper(vectorMapperMem);

Here my inputs (maybe it come form this, but I don’t think so) :

imageVectorMem->SetDimensions(dim[0],dim[1],dim[2]);
imageVectorMem->SetSpacing(spacing[0],spacing[1],spacing[2]);
imageVectorMem->SetOrigin(0,0,0);
imageVectorMem->AllocateScalars(VTK_FLOAT, 3);
int idx =0;

for (int i = 0; i < dim[2]; i ++)
{
	for (int j = 0; j < dim[1]; j ++)
	{
		for (int k = 0; k < dim[0]; k ++,  idx ++ )
		{
			float* dataDef = static_cast<float*>(imageVectorMem->GetScalarPointer(k, j, i));
			dataDef[0] = dataToDisplay->vectorField.at(idx)[0];
			dataDef[1] = dataToDisplay->vectorField.at(idx)[1];
			dataDef[2] = dataToDisplay->vectorField.at(idx)[2];
		}
	}
}

//imageVectorMem->GetPointData()->SetActiveScalars("ImageScalars");
imageVectorMem->GetPointData()->SetActiveVectors(imageVectorMem->GetPointData()->GetArray(0)->GetName());

You must call Update() before calling GetOutput():

imageResliceMem->Update();
...
imageVectorSliceMem->CopyStructure(imageResliceMem->GetOutput());

Since the code that creates imageVectorMem2 calls AllocateScalars() and GetScalarPointer(), your vector data is already stored as Scalars, so you do not need imageVectorMem2, and you do not need this before using vtkImageReslice:

imageVectorMem->GetPointData()->SetActiveVectors(imageVectorMem->GetPointData()->GetArray(0)->GetName());

Still not working …

image

I only get these 4 arrows when I’m supposed to get 672 400 arrows

And I don’t know why they seem to still be not oriented in the 3D space, they lose there color and the image isn’t fix anymore like if, the arrow wasn’t assign to they point in the image. Really strange …

Check the input to the glyph filter to see if you can get some clues. E.g. print out the following values:

imageVectorSliceMem->GetNumberOfPoints();
imageVectorSliceMem->GetPointData()->GetVectors()->GetNumberOfTuples();
imageVectorSliceMem->GetPointData()->GetVectors()->GetNumberOfComponents();

Also check some of the actual values to make sure that they’re not all (0,0,0).

It seems it comes from the moment I convert the data to vector type, but I don’t understand why it doesn’t associate rightfully the data.

imageVectorSliceMem->CopyStructure(imageResliceMem->GetOutput());
imageVectorSliceMem->GetPointData()->SetVectors(imageResliceMem->GetOutput()->GetPointData()->GetScalars());

Are you sure you called imageResliceMem->Update() before calling imageResliceMem->GetOutput()?

Also check imageResliceMem->GetOutput()->GetNumberOfPoints().

Well, … I think I use it correctly

It also return 4 …
I really do not understand what Reslice on doing

imageVectorMem = vtkSmartPointer<vtkImageData>::New();

imageResliceMem = vtkSmartPointer<vtkImageReslice>::New();
imageResliceMem->SetInputData(imageVectorMem);
imageResliceMem->SetOutputDimensionality(2);
imageResliceMem->SetInterpolationMode(true ? VTK_RESLICE_LINEAR : VTK_RESLICE_NEAREST);
imageResliceMem->SetInterpolationMode(true);

imageResliceMem->Update();
	
imageVectorSliceMem = vtkSmartPointer<vtkImageData>::New();
imageVectorSliceMem->AllocateScalars(VTK_FLOAT, 3);
imageVectorSliceMem->SetOrigin(imageVectorMem->GetOrigin());
imageVectorSliceMem->CopyStructure(imageResliceMem->GetOutput());
imageVectorSliceMem->GetPointData()->SetVectors(imageResliceMem->GetOutput()->GetPointData()->GetScalars());
imageVectorSliceMem->GetPointData()->SetActiveVectors("ImageScalars");
	
cout << imageVectorSliceMem->GetNumberOfPoints() << endl; // return 4
cout << imageVectorSliceMem->GetPointData()->GetVectors() << endl; // return 00000...
cout << imageResliceMem->GetOutput()->GetNumberOfPoints() << endl; // return 4
//cout << imageVectorSliceMem->GetPointData()->GetVectors()->GetNumberOfTuples() << endl; // CRASH, no reading rights
//cout << imageVectorSliceMem->GetPointData()->GetVectors()->GetNumberOfComponents() <<endl; // CRASH, no reading rights

arrowSourceMem = vtkSmartPointer<vtkArrowSource>::New();
glyphFilterMem = vtkSmartPointer<vtkGlyph3D>::New();
glyphFilterMem->SetSourceConnection(arrowSourceMem->GetOutputPort());
glyphFilterMem->SetInputData(imageVectorSliceMem);
glyphFilterMem->SetVectorModeToUseVector();  
glyphFilterMem->OrientOn(); 

vectorMapperMem = vtkSmartPointer<vtkPolyDataMapper>::New();
vectorMapperMem->SetInputConnection(glyphFilterMem->GetOutputPort());

actorMem = vtkSmartPointer<vtkActor>::New();
actorMem->SetMapper(vectorMapperMem);

Strange. When you “Set” something, generally a “Get” will return exactly what you “Set”. It certainly does so when I try the following on my computer:

imageVectorSliceMem->GetPointData()->SetVectors(imageResliceMem->GetOutput()->GetPointData()->GetScalars());
cout << imageVectorSliceMem->GetPointData()->GetVectors() << endl;

Are you absolutely sure that the following isn’t also returning zero?

cout << imageResliceMem->GetOutput()->GetPointData()->GetScalars() << endl;

Also, never call AllocateScalars() immediately after calling New(). It’s always necessary to set the Extent (or Dimensions) of the data before AllocateScalars(). Internally, y->CopyStructure(x) sets the Extent, Spacing, and Origin of y to the Extent, Spacing, and Origin of x.

Ok ! It seems that the AllocateScalars() was bugging my code, so now I place it after the :
imageVectorSliceMem->CopyStructure(imageResliceMem->GetOutput());
And now I get some result at the output but my arrows still do not display:

Well I guess there is no solution for me …

I started to developpe my own Reslice to be able to reslice my vectors and I start to get some good result.

Thanks for your help David