diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.cpp index e810e83622..cc4e16aa53 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.cpp @@ -1,201 +1,397 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkUSNavigationStepCtUsRegistration.h" #include "ui_QmitkUSNavigationStepCtUsRegistration.h" #include "mitkNodeDisplacementFilter.h" #include "../QmitkUSNavigationMarkerPlacement.h" #include #include #include #include "mitkProperties.h" +#include +#include + +#include +#include + + QmitkUSNavigationStepCtUsRegistration::QmitkUSNavigationStepCtUsRegistration(QWidget *parent) : QmitkUSAbstractNavigationStep(parent), ui(new Ui::QmitkUSNavigationStepCtUsRegistration) { this->UnsetFloatingImageGeometry(); this->DefineDataStorageImageFilter(); this->CreateQtPartControl(this); } QmitkUSNavigationStepCtUsRegistration::~QmitkUSNavigationStepCtUsRegistration() { delete ui; } bool QmitkUSNavigationStepCtUsRegistration::OnStartStep() { MITK_INFO << "OnStartStep()"; return true; } bool QmitkUSNavigationStepCtUsRegistration::OnStopStep() { MITK_INFO << "OnStopStep()"; return true; } bool QmitkUSNavigationStepCtUsRegistration::OnFinishStep() { MITK_INFO << "OnFinishStep()"; return true; } bool QmitkUSNavigationStepCtUsRegistration::OnActivateStep() { MITK_INFO << "OnActivateStep()"; ui->floatingImageComboBox->SetDataStorage(this->GetDataStorage()); ui->fiducialMarkerModelPointSetComboBox->SetDataStorage(this->GetDataStorage()); + ui->devMarkerComboBox->SetDataStorage(this->GetDataStorage()); return true; } bool QmitkUSNavigationStepCtUsRegistration::OnDeactivateStep() { MITK_INFO << "OnDeactivateStep()"; return true; } void QmitkUSNavigationStepCtUsRegistration::OnUpdate() { if (m_NavigationDataSource.IsNull()) { return; } m_NavigationDataSource->Update(); } void QmitkUSNavigationStepCtUsRegistration::OnSettingsChanged(const itk::SmartPointer settingsNode) { } QString QmitkUSNavigationStepCtUsRegistration::GetTitle() { return "CT-to-US registration"; } QmitkUSAbstractNavigationStep::FilterVector QmitkUSNavigationStepCtUsRegistration::GetFilter() { return FilterVector(); } void QmitkUSNavigationStepCtUsRegistration::OnSetCombinedModality() { mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetCombinedModality(false); if (combinedModality.IsNotNull()) { m_NavigationDataSource = combinedModality->GetNavigationDataSource(); } } void QmitkUSNavigationStepCtUsRegistration::UnsetFloatingImageGeometry() { m_ImageDimension[0] = 0; m_ImageDimension[1] = 0; m_ImageDimension[2] = 0; m_ImageSpacing[0] = 1; m_ImageSpacing[1] = 1; m_ImageSpacing[2] = 1; } void QmitkUSNavigationStepCtUsRegistration::SetFloatingImageGeometryInformation(mitk::Image * image) { m_ImageDimension[0] = image->GetDimension(0); m_ImageDimension[1] = image->GetDimension(1); m_ImageDimension[2] = image->GetDimension(2); m_ImageSpacing[0] = image->GetGeometry()->GetSpacing()[0]; m_ImageSpacing[1] = image->GetGeometry()->GetSpacing()[1]; m_ImageSpacing[2] = image->GetGeometry()->GetSpacing()[2]; } void QmitkUSNavigationStepCtUsRegistration::DefineDataStorageImageFilter() { m_IsAPointSetPredicate = mitk::TNodePredicateDataType::New(); mitk::TNodePredicateDataType::Pointer isImage = mitk::TNodePredicateDataType::New(); auto isSegmentation = mitk::NodePredicateDataType::New("Segment"); mitk::NodePredicateOr::Pointer validImages = mitk::NodePredicateOr::New(); validImages->AddPredicate(mitk::NodePredicateAnd::New(isImage, mitk::NodePredicateNot::New(isSegmentation))); mitk::NodePredicateNot::Pointer isNotAHelperObject = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true))); m_IsOfTypeImagePredicate = mitk::NodePredicateAnd::New(validImages, isNotAHelperObject); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateNot::Pointer isNotBinaryPredicate = mitk::NodePredicateNot::New(isBinaryPredicate); mitk::NodePredicateAnd::Pointer isABinaryImagePredicate = mitk::NodePredicateAnd::New(m_IsOfTypeImagePredicate, isBinaryPredicate); mitk::NodePredicateAnd::Pointer isNotABinaryImagePredicate = mitk::NodePredicateAnd::New(m_IsOfTypeImagePredicate, isNotBinaryPredicate); m_IsASegmentationImagePredicate = mitk::NodePredicateOr::New(isABinaryImagePredicate, mitk::TNodePredicateDataType::New()); m_IsAPatientImagePredicate = mitk::NodePredicateAnd::New(isNotABinaryImagePredicate, mitk::NodePredicateNot::New(mitk::TNodePredicateDataType::New())); } void QmitkUSNavigationStepCtUsRegistration::CreateQtPartControl(QWidget *parent) { ui->setupUi(parent); ui->floatingImageComboBox->SetPredicate(m_IsAPatientImagePredicate); ui->fiducialMarkerModelPointSetComboBox->SetPredicate(m_IsAPointSetPredicate); + ui->devMarkerComboBox->SetPredicate(m_IsAPointSetPredicate); // create signal/slot connections connect(ui->floatingImageComboBox, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnFloatingImageComboBoxSelectionChanged(const mitk::DataNode*))); + connect(ui->fiducialMarkerModelPointSetComboBox, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), + this, SLOT(OnFiducialMarkerModelComboBoxSelectionChanged(const mitk::DataNode*))); + connect(ui->devMarkerComboBox, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), + this, SLOT(OnDevComboBoxChanged(const mitk::DataNode*))); + connect(ui->doRegistrationMarkerToImagePushButton, SIGNAL(clicked()), + this, SLOT(OnRegisterMarkerToFloatingImageCS())); } void QmitkUSNavigationStepCtUsRegistration::OnFloatingImageComboBoxSelectionChanged(const mitk::DataNode* node) { MITK_INFO << "OnFloatingImageComboBoxSelectionChanged()"; if (m_FloatingImage.IsNotNull()) { //TODO: Define, what will happen if the imageCT is not null... } if (node == nullptr) { this->UnsetFloatingImageGeometry(); m_FloatingImage = nullptr; return; } mitk::DataNode* selectedFloatingImage = ui->floatingImageComboBox->GetSelectedNode(); if (selectedFloatingImage == nullptr) { this->UnsetFloatingImageGeometry(); m_FloatingImage = nullptr; return; } mitk::Image::Pointer floatingImage = dynamic_cast(selectedFloatingImage->GetData()); if (floatingImage.IsNull()) { MITK_WARN << "Failed to cast selected segmentation node to mitk::Image*"; this->UnsetFloatingImageGeometry(); m_FloatingImage = nullptr; return; } m_FloatingImage = floatingImage; this->SetFloatingImageGeometryInformation(floatingImage.GetPointer()); } + +void QmitkUSNavigationStepCtUsRegistration::OnFiducialMarkerModelComboBoxSelectionChanged(const mitk::DataNode * node) +{ + MITK_INFO << "OnFiducialMarkerModelComboBoxSelectionChanged()"; + + if (m_MarkerModelCoordinateSystemPointSet.IsNotNull()) + { + //TODO: Define, what will happen if the pointSet is not null... + } + + if (node == nullptr) + { + m_MarkerModelCoordinateSystemPointSet = nullptr; + return; + } + + mitk::DataNode* selectedPointSet = ui->fiducialMarkerModelPointSetComboBox->GetSelectedNode(); + if (selectedPointSet == nullptr) + { + m_MarkerModelCoordinateSystemPointSet = nullptr; + return; + } + + mitk::PointSet::Pointer pointSet = dynamic_cast(selectedPointSet->GetData()); + if (pointSet.IsNull()) + { + MITK_WARN << "Failed to cast selected pointset node to mitk::PointSet*"; + m_MarkerModelCoordinateSystemPointSet = nullptr; + return; + } + + m_MarkerModelCoordinateSystemPointSet = pointSet; +} + +void QmitkUSNavigationStepCtUsRegistration::OnDevComboBoxChanged(const mitk::DataNode * node) +{ + if (node == nullptr) + { + m_MarkerFloatingImageCoordinateSystemPointSet = nullptr; + return; + } + + mitk::DataNode* selectedPointSet = ui->devMarkerComboBox->GetSelectedNode(); + if (selectedPointSet == nullptr) + { + m_MarkerFloatingImageCoordinateSystemPointSet = nullptr; + return; + } + + mitk::PointSet::Pointer pointSet = dynamic_cast(selectedPointSet->GetData()); + if (pointSet.IsNull()) + { + MITK_WARN << "Failed to cast selected pointset node to mitk::PointSet*"; + m_MarkerFloatingImageCoordinateSystemPointSet = nullptr; + return; + } + + m_MarkerFloatingImageCoordinateSystemPointSet = pointSet; +} + +void QmitkUSNavigationStepCtUsRegistration::OnRegisterMarkerToFloatingImageCS() +{ + //Check for initialization + if( m_MarkerModelCoordinateSystemPointSet.IsNull() || + m_MarkerFloatingImageCoordinateSystemPointSet.IsNull() ) + { + MITK_WARN << "Fiducial Landmarks are not initialized yet, cannot register"; + return; + } + + //Retrieve fiducials + if (m_MarkerFloatingImageCoordinateSystemPointSet->GetSize() != m_MarkerModelCoordinateSystemPointSet->GetSize()) + { + MITK_WARN << "Not the same number of fiducials, cannot register"; + return; + } + else if (m_MarkerFloatingImageCoordinateSystemPointSet->GetSize() < 3) + { + MITK_WARN << "Need at least 3 fiducials, cannot register"; + return; + } + + //############### conversion to vtk data types (we will use the vtk landmark based transform) ########################## + //convert point sets to vtk poly data + vtkSmartPointer sourcePoints = vtkSmartPointer::New(); + vtkSmartPointer targetPoints = vtkSmartPointer::New(); + for (int i = 0; iGetSize(); i++) + { + double point[3] = { m_MarkerModelCoordinateSystemPointSet->GetPoint(i)[0], + m_MarkerModelCoordinateSystemPointSet->GetPoint(i)[1], + m_MarkerModelCoordinateSystemPointSet->GetPoint(i)[2] }; + sourcePoints->InsertNextPoint(point); + + double point_targets[3] = { m_MarkerFloatingImageCoordinateSystemPointSet->GetPoint(i)[0], + m_MarkerFloatingImageCoordinateSystemPointSet->GetPoint(i)[1], + m_MarkerFloatingImageCoordinateSystemPointSet->GetPoint(i)[2] }; + targetPoints->InsertNextPoint(point_targets); + } + + //########################### here, the actual transform is computed ########################## + //compute transform + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->SetSourceLandmarks(sourcePoints); + transform->SetTargetLandmarks(targetPoints); + transform->SetModeToRigidBody(); + transform->Modified(); + transform->Update(); + //compute FRE of transform + + double FRE = mitk::StaticIGTHelperFunctions::ComputeFRE(m_MarkerModelCoordinateSystemPointSet, m_MarkerFloatingImageCoordinateSystemPointSet, transform); + MITK_INFO << "FRE: " << FRE << " mm"; + + //############################################################################################# + + //############### conversion back to itk/mitk data types ########################## + //convert from vtk to itk data types + itk::Matrix rotationFloat = itk::Matrix(); + itk::Vector translationFloat = itk::Vector(); + itk::Matrix rotationDouble = itk::Matrix(); + itk::Vector translationDouble = itk::Vector(); + + vtkSmartPointer m = transform->GetMatrix(); + for (int k = 0; k<3; k++) for (int l = 0; l<3; l++) + { + rotationFloat[k][l] = m->GetElement(k, l); + rotationDouble[k][l] = m->GetElement(k, l); + + } + for (int k = 0; k<3; k++) + { + translationFloat[k] = m->GetElement(k, 3); + translationDouble[k] = m->GetElement(k, 3); + } + //create affine transform 3D surface + mitk::AffineTransform3D::Pointer mitkTransform = mitk::AffineTransform3D::New(); + mitkTransform->SetMatrix(rotationDouble); + mitkTransform->SetOffset(translationDouble); + //################################################################ + + //############### object is transformed ########################## + //save transform + //this is stored in a member because it is needed for permanent registration later on + m_TransformMarkerCSToFloatingImageCS = mitk::NavigationData::New(mitkTransform); + MITK_INFO << mitkTransform; + //transform surface/image + //only move image if we have one. Sometimes, this widget is used just to register point sets without images. + /*if (m_ImageNode.IsNotNull()) + { + //first we have to store the original ct image transform to compose it with the new transform later + mitk::AffineTransform3D::Pointer imageTransform = m_ImageNode->GetData()->GetGeometry()->GetIndexToWorldTransform(); + imageTransform->Compose(mitkTransform); + mitk::AffineTransform3D::Pointer newImageTransform = mitk::AffineTransform3D::New(); //create new image transform... setting the composed directly leads to an error + itk::Matrix rotationFloatNew = imageTransform->GetMatrix(); + itk::Vector translationFloatNew = imageTransform->GetOffset(); + newImageTransform->SetMatrix(rotationFloatNew); + newImageTransform->SetOffset(translationFloatNew); + m_ImageNode->GetData()->GetGeometry()->SetIndexToWorldTransform(newImageTransform); + }*/ + + //If this option is set, each point will be transformed and the acutal coordinates of the points change. + /*if (this->m_Controls->m_MoveImagePoints->isChecked()) + { + mitk::PointSet* pointSet_orig = dynamic_cast(m_ImageFiducialsNode->GetData()); + mitk::PointSet::Pointer pointSet_moved = mitk::PointSet::New(); + + for (int i = 0; i < pointSet_orig->GetSize(); i++) + { + pointSet_moved->InsertPoint(mitkTransform->TransformPoint(pointSet_orig->GetPoint(i))); + } + + pointSet_orig->Clear(); + for (int i = 0; i < pointSet_moved->GetSize(); i++) + pointSet_orig->InsertPoint(pointSet_moved->GetPoint(i)); + }*/ + + //Do a global reinit + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); + +} + + diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.h b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.h index 47f5767815..a47fa7f32a 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.h +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.h @@ -1,138 +1,145 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKUSNAVIGATIONSTEPCTUSREGISTRATION_H #define QMITKUSNAVIGATIONSTEPCTUSREGISTRATION_H #include "QmitkUSAbstractNavigationStep.h" #include #include #include #include #include namespace itk { template class SmartPointer; } namespace mitk { class NodeDisplacementFilter; class NavigationDataSource; } namespace Ui { class QmitkUSNavigationStepCtUsRegistration; } /** * \brief Navigation step for marking risk structures. * The user can add risk structures by interacting with the render windows. The * risk structures are organized in an embedded table view. * * The risk structures are stored under DATANAME_BASENODE -> DATANAME_ZONES. * * This step is ready for the next step directly after activating. All actions * to be done in this step are optional. */ class QmitkUSNavigationStepCtUsRegistration : public QmitkUSAbstractNavigationStep { Q_OBJECT public: explicit QmitkUSNavigationStepCtUsRegistration(QWidget *parent = 0); ~QmitkUSNavigationStepCtUsRegistration(); /** * \brief Initialization of the data storage nodes. * \return always true */ virtual bool OnStartStep(); /** * \brief Resets widget and filter and removes nodes from the data storage. * \return always true */ virtual bool OnStopStep(); /** * \brief There is nothing to be done. * \return always true */ virtual bool OnFinishStep(); /** * \brief Selects input for the node displacement filter and emits "ReadyForNextStep" signal. * The input selection cannot be done earlier. * \return */ virtual bool OnActivateStep(); virtual bool OnDeactivateStep(); /** * \brief Updates just the tracking validity status. */ virtual void OnUpdate(); /** * The property "settings.interaction-concept" is used. */ virtual void OnSettingsChanged(const itk::SmartPointer settingsNode); virtual QString GetTitle(); /** * @return a node displacement filter for the zone surfaces */ virtual FilterVector GetFilter(); protected: virtual void OnSetCombinedModality(); void UnsetFloatingImageGeometry(); void SetFloatingImageGeometryInformation(mitk::Image* image); void DefineDataStorageImageFilter(); void CreateQtPartControl(QWidget *parent); protected slots: void OnFloatingImageComboBoxSelectionChanged(const mitk::DataNode* node); + void OnFiducialMarkerModelComboBoxSelectionChanged(const mitk::DataNode* node); + void OnDevComboBoxChanged(const mitk::DataNode* node); + void OnRegisterMarkerToFloatingImageCS(); private: Ui::QmitkUSNavigationStepCtUsRegistration *ui; mitk::NodePredicateAnd::Pointer m_IsOfTypeImagePredicate; mitk::NodePredicateOr::Pointer m_IsASegmentationImagePredicate; mitk::NodePredicateAnd::Pointer m_IsAPatientImagePredicate; mitk::TNodePredicateDataType::Pointer m_IsAPointSetPredicate; itk::SmartPointer m_NavigationDataSource; mitk::Image::Pointer m_FloatingImage; + mitk::PointSet::Pointer m_MarkerModelCoordinateSystemPointSet; + mitk::PointSet::Pointer m_MarkerFloatingImageCoordinateSystemPointSet; + + mitk::NavigationData::Pointer m_TransformMarkerCSToFloatingImageCS; /*! \brief The 3D dimension of the CT image given in index size. */ mitk::Vector3D m_ImageDimension; mitk::Vector3D m_ImageSpacing; }; #endif // QMITKUSNAVIGATIONSTEPCTUSREGISTRATION_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.ui b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.ui index 0cc70c1966..7419809968 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.ui +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.ui @@ -1,63 +1,80 @@ QmitkUSNavigationStepCtUsRegistration 0 0 400 395 Form Selected Floating Image: Selected Fiducial Marker Model Point Set + + + + For development purposes: künstliche Marker-PointSet in FloatingImage CS + + + + + + + + + + Do Registration Marker CS -> Floating Image CS + + + Qt::Vertical 20 40 QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h