[vtkusers] Correct anatomical orientation of volumes from Niftii and DICOM

ochampao ochampao at hotmail.com
Wed May 16 07:15:45 EDT 2018


Hi David,

I've used your suggestion to verify the camera configuration with
vtkAxesActor. In combination with the AnatomicalOrientation [1] example, it
was very helpful. I think now I've setup the camera in the 3 views to follow
(hopefully correctly) the RAS coordinate system convention. See screenshot
with the axes.

<http://vtk.1045678.n5.nabble.com/file/t341857/2018-05-16_10_29_01-kPlan_TPM.png> 

I have also switched to using vtkDICOMReader (vtk-dicom 0.87 + VTK8.1) for
loading from DICOM. This is so that I can make use of the vtkDICOMToRAS
class to account for the change in coordinate system from LPS to RAS (until
I am comfortable enough to write my own conversion methods). See loadDicom()
method below. Despite making these changes I still see the images flipped
horizontally (referring to the axial view and also comparing with Slicer
which as I understand also uses RAS). 

<http://vtk.1045678.n5.nabble.com/file/t341857/2018-05-16_12_12_42-kPlan_TPM.png> 

Assumuing my camera setup is indeed correct, shouldn't vtkDICOMToRAS account
for the switch in coordinates? Are some steps missing? Why do I see this
horizontal flip?

I've included below the relevant code for setting up the cameras and loading
Dicom.

Thanks for your help.
Panos.

[1] 
https://lorensen.github.io/VTKExamples/site/Cxx/VisualizationAlgorithms/AnatomicalOrientation/
<https://lorensen.github.io/VTKExamples/site/Cxx/VisualizationAlgorithms/AnatomicalOrientation/>  

// ================================================
//     loadDicom()
// ================================================
vtkSmartPointer<vtkImageData> QuadView::loadDicom(const char* path) const
{
	vtkNew<vtkGlobFileNames> fileGlob;
	fileGlob->SetDirectory(path);
	fileGlob->AddFileNames("*.dcm");
	vtkSmartPointer<vtkStringArray> vtkStringFilenames =
fileGlob->GetFileNames();

	vtkNew<vtkDICOMReader> reader;
	reader->SetFileNames(vtkStringFilenames);
	reader->SetMemoryRowOrderToFileNative();
	reader->UpdateInformation();

	vtkNew<vtkDICOMToRAS> converterLPSToRAS;
	converterLPSToRAS->SetInputConnection(reader->GetOutputPort());
	converterLPSToRAS->SetPatientMatrix(reader->GetPatientMatrix());
	converterLPSToRAS->SetAllowRowReordering(true);
	converterLPSToRAS->SetAllowColumnReordering(true);
	converterLPSToRAS->UpdateMatrix();
	converterLPSToRAS->Update();

	return converterLPSToRAS->GetOutput();
}

// ================================================
//     resetCameras2D()
// ================================================
void QuadView::resetCameras2D() const 
{ 
    // iterate through the active 2D views. 
    for (const auto &view : mQuadViewUI.getQVTKOpenGLWidget2DKeyList()) 
    { 
        // Reset camera & clipping range 
        mPipelineObject2DContainer.at(view).renderer->ResetCamera(); 

        switch (view)
		{
			case IQuadViewUI::VTKDockWidget::TopLeft: //Axial
			{
				double viewUp[3] = { 0, 1, 0 };
				double leftToRight[3] = { 1, 0, 0 };
				vtkCamera* camera = 
					mPipelineObject2DContainer.at(view).renderer->GetActiveCamera();

				setImageOrientation(leftToRight, viewUp, *camera);
				camera->OrthogonalizeViewUp();
				break;
			}
			case IQuadViewUI::VTKDockWidget::TopRight: //Sagittal
			{
				double viewUp[3] = { 0, 0, 1 };
				double leftToRight[3] = { 0, -1, 0 };
				vtkCamera* camera = 
					mPipelineObject2DContainer.at(view).renderer->GetActiveCamera();

				setImageOrientation(leftToRight, viewUp, *camera);
				camera->OrthogonalizeViewUp();
				break;
			}
			case IQuadViewUI::VTKDockWidget::BottomLeft: //Coronal
			{
				double viewUp[3] = { 0, 0, 1 };
				double leftToRight[3] = { 1, 0, 0 };
				vtkCamera* camera = 
					mPipelineObject2DContainer.at(view).renderer->GetActiveCamera();

				setImageOrientation(leftToRight, viewUp, *camera);
				camera->OrthogonalizeViewUp();
				break;
			}
			default:
				break;
		}
    } 
} 

// ================================================
//     setImageOrientation()
// ================================================
void QuadView::setImageOrientation(const double leftToRight[3], const double
viewUp[3], vtkCamera &camera) const
{
	// from vtkInteractorStyleImage::SetImageOrientation()
	
	// compute the view plane normal, which points out of the screen, through
the cross product
	double normal[3]; 
	vtkMath::Cross(leftToRight, viewUp, normal);

	// get the camera focus
	double focus[3];
	camera.GetFocalPoint(focus);

	// get the camera distance from the focus
	double d = camera.GetDistance();

	// position the camera on view plane normal keeping the focus and the
distance from it fixed
	camera.SetPosition(
		focus[0] + d*normal[0],
		focus[1] + d*normal[1],
		focus[2] + d*normal[2]);

	// make sure focus is the same
	camera.SetFocalPoint(focus);

	// setup view up vector
	camera.SetViewUp(viewUp);
}



--
Sent from: http://vtk.1045678.n5.nabble.com/VTK-Users-f1224199.html


More information about the vtkusers mailing list