[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