Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
QmitkFiducialRegistrationWidget.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
14 
15 #include <vtkTransform.h>
16 #include <vtkTransformPolyDataFilter.h>
17 #include <vtkAppendPolyData.h>
18 #include <vtkPoints.h>
19 #include <vtkLandmarkTransform.h>
21 
22 #include <mitkRenderingManager.h>
23 
24 #define FRW_LOG MITK_INFO("Fiducial Registration Widget")
25 #define FRW_WARN MITK_WARN("Fiducial Registration Widget")
26 #define FRW_DEBUG MITK_DEBUG("Fiducial Registration Widget")
27 
28 /* VIEW MANAGEMENT */
30 : QWidget(parent), m_Controls(nullptr),m_MultiWidget(nullptr), m_ImageFiducialsNode(nullptr), m_TrackerFiducialsNode(nullptr)
31 {
32  CreateQtPartControl(this);
33 }
34 
35 
37 {
38  m_Controls = nullptr;
39 
40  //clean up data nodes
41  if (m_DataStorage.IsNotNull())
42  {
45  }
46 }
47 
48 
50 {
51  if (!m_Controls)
52  {
53  // create GUI widgets
54  m_Controls = new Ui::QmitkFiducialRegistrationWidget;
55  m_Controls->setupUi(parent);
56 
57  // hide additional image fiducial button
58  m_Controls->m_AddImageFiducialBtn->setHidden(true);
59 
60  m_Controls->m_spaceHolderGroupBox->setStyleSheet("QGroupBox {border: 0px transparent;}");
61  m_Controls->m_spaceHolderGroupBox2->setStyleSheet("QGroupBox {border: 0px transparent;}");
62 
63  this->CreateConnections();
64  }
65 }
66 
67 
69 {
70  connect( (QObject*)(m_Controls->m_AddTrackingFiducialBtn), SIGNAL(clicked()), this, SIGNAL(AddedTrackingFiducial()) );
71  connect((QObject*)(m_Controls->m_AddTrackingFiducialBtn), SIGNAL(clicked()), this, SLOT(AddTrackerPoint()));
72  connect( (QObject*)(m_Controls->m_AddImageFiducialBtn), SIGNAL(clicked()), this, SIGNAL(AddedImageFiducial()) );
73  connect( (QObject*)(m_Controls->m_RegisterFiducialsBtn), SIGNAL(clicked()), this, SIGNAL(PerformFiducialRegistration()) );
74  connect((QObject*)(m_Controls->m_RegisterFiducialsBtn), SIGNAL(clicked()), this, SLOT(Register()));
75  connect( (QObject*)(m_Controls->m_UseICPRegistration), SIGNAL(toggled(bool)), this, SIGNAL(FindFiducialCorrespondences(bool)) );
76 
77  //unselects the edit button of the other widget if one is selected
78  connect( (QObject*)(m_Controls->m_RegistrationImagePoints), SIGNAL(EditPointSets(bool)), this, SLOT(DisableEditButtonRegistrationTrackingPoints(bool)));
79  connect( (QObject*)(m_Controls->m_RegistrationTrackingPoints), SIGNAL(EditPointSets(bool)), this, SLOT(DisableEditButtonRegistrationImagePoints(bool)));
80 }
81 
83 {
84 if (activated) m_Controls->m_RegistrationImagePoints->UnselectEditButton();
85 }
87 {
88 if (activated) m_Controls->m_RegistrationTrackingPoints->UnselectEditButton();
89 }
90 
92 {
93  if (widgetMode==LANDMARKMODE)
94  {
99  this->HideImageFiducialButton(false);
100  this->m_Controls->sourceLandmarksGroupBox->setTitle("Target/Reference landmarks");
101  this->m_Controls->targetLandmarksGroupBox->setTitle("Source Landmarks");
102  this->m_Controls->m_AddImageFiducialBtn->setText("Add target landmark");
103  this->m_Controls->m_AddTrackingFiducialBtn->setText("Add source landmark");
104  }
105  else if (widgetMode==FIDUCIALMODE)
106  {
110  this->HideUseICPRegistrationCheckbox(false);
111  this->HideImageFiducialButton(true);
112  this->m_Controls->sourceLandmarksGroupBox->setTitle("Image fiducials");
113  this->m_Controls->targetLandmarksGroupBox->setTitle("OR fiducials");
114  this->m_Controls->m_AddImageFiducialBtn->setText("Add image fiducial");
115  this->m_Controls->m_AddTrackingFiducialBtn->setText("Add current instrument position");
116  }
117 }
118 
120 {
121  if (text == nullptr)
122  return;
123  m_Controls->m_RegistrationQualityDisplay->setText(text); // set text on the QLabel
124 }
125 
127 {
128  if(m_Controls->m_UseICPRegistration->isChecked())
129  return true;
130  else
131  return false;
132 }
133 
135 {
136  if(imageFiducialsNode.IsNull())
137  {
138  FRW_WARN<< "tracker fiducial node is nullptr";
139  return;
140  }
141  m_Controls->m_RegistrationImagePoints->SetPointSetNode(imageFiducialsNode); // pass node to pointListWidget
142  if(m_MultiWidget == nullptr)
143  {
144  MITK_DEBUG<< "stdMultiWidget is nullptr";
145  return;
146  }
147  m_Controls->m_RegistrationImagePoints->SetMultiWidget(m_MultiWidget); // pass multiWidget to pointListWidget
148 }
149 
151 {
152  if(trackerFiducialsNode.IsNull())
153  {
154  FRW_WARN<< "tracker fiducial node is nullptr";
155  return;
156  }
157  m_Controls->m_RegistrationTrackingPoints->SetPointSetNode(trackerFiducialsNode); // pass node to pointListWidget
158  if(m_MultiWidget == nullptr)
159  {
160  MITK_DEBUG<< "stdMultiWidget is nullptr";
161  return;
162  }
163  m_Controls->m_RegistrationTrackingPoints->SetMultiWidget(m_MultiWidget); // pass multiWidget to pointListWidget
164 }
165 
167 {
168  m_MultiWidget=multiWidget;
169 }
170 
172 {
173  m_Controls->m_RegistrationTrackingPoints->AddSliceNavigationController(snc);
174  m_Controls->m_RegistrationImagePoints->AddSliceNavigationController(snc);
175 }
176 
178 {
179  return m_ImageFiducialsNode;
180 }
181 
183 {
184  return m_TrackerFiducialsNode;
185 }
186 
188 {
189  m_Controls->m_rbStaticRegistration->setHidden(on);
191 }
192 
194 {
195  m_Controls->m_rbContinousRegistration->setHidden(on);
197 }
198 
200 {
201  if (m_Controls->m_rbStaticRegistration->isHidden() && m_Controls->m_rbContinousRegistration->isHidden())
202  {
203  m_Controls->m_gbFiducialRegistration->setHidden(true);
204  }
205  else
206  {
207  m_Controls->m_gbFiducialRegistration->setHidden(false);
208  }
209 }
210 
212 {
213  m_Controls->m_UseICPRegistration->setHidden(on);
214 }
215 
217 {
218  m_Controls->m_AddImageFiducialBtn->setHidden(on);
220 
221 }
222 
224 {
225  m_Controls->m_AddTrackingFiducialBtn->setHidden(on);
227 }
228 
230 {
231  if (m_Controls->m_AddImageFiducialBtn->isHidden() && m_Controls->m_AddTrackingFiducialBtn->isHidden())
232  {
233  m_Controls->m_spaceHolderGroupBox->setHidden(true);
234  m_Controls->m_spaceHolderGroupBox2->setHidden(true);
235  }
236  else
237  {
238  m_Controls->m_spaceHolderGroupBox->setHidden(false);
239  m_Controls->m_spaceHolderGroupBox2->setHidden(false);
240  }
241 }
242 
244 {
245  QString groupBoxTitle = sourceLandmarkName;
246  groupBoxTitle.append(" Landmarks");
247  m_Controls->sourceLandmarksGroupBox->setTitle(groupBoxTitle);
248  QString buttonText = "Add ";
249  buttonText.append(sourceLandmarkName);
250  buttonText.append(" Landmark");
251  m_Controls->m_AddImageFiducialBtn->setText(buttonText);
252 }
253 
255 {
256  QString groupBoxTitle = targetLandmarkName;
257  groupBoxTitle.append(" Landmarks");
258  m_Controls->targetLandmarksGroupBox->setTitle(groupBoxTitle);
259  QString buttonText = "Add ";
260  buttonText.append(targetLandmarkName);
261  buttonText.append(" Landmark");
262  m_Controls->m_AddTrackingFiducialBtn->setText(buttonText);
263 }
264 
266 {
267  m_ImageNode = i;
268 }
269 
271 {
273 }
274 
276 {
277  m_DataStorage = d;
278 
279  mitk::DataNode::Pointer ImageFiducialsNode = mitk::DataNode::New();
281  ImageFiducialsNode->SetData(imagePointSet);
282  ImageFiducialsNode->SetName("Image Point Set");
283  m_DataStorage->Add(ImageFiducialsNode);
284  this->SetImageFiducialsNode(ImageFiducialsNode);
285  m_ImageFiducialsNode = ImageFiducialsNode;
286 
287  mitk::DataNode::Pointer TrackerFiducialsNode = mitk::DataNode::New();
288  mitk::PointSet::Pointer trackerPointSet = mitk::PointSet::New();
289  TrackerFiducialsNode->SetData(trackerPointSet);
290  TrackerFiducialsNode->SetName("Tracker Point Set");
291  m_DataStorage->Add(TrackerFiducialsNode);
292  this->SetTrackerFiducialsNode(TrackerFiducialsNode);
293  m_TrackerFiducialsNode = TrackerFiducialsNode;
294 }
295 
297 {
298  if (m_DataStorage.IsNull()) { return ; } //here the widget should simply do nothing (for backward compatibility)
299  else if (m_TrackerNavigationData.IsNull() || m_TrackerFiducialsNode.IsNull()) { MITK_WARN << "Tracker node not correctly initialized"; return; }
300  mitk::PointSet::Pointer ps = dynamic_cast<mitk::PointSet*>(m_TrackerFiducialsNode->GetData());
301  ps->InsertPoint(ps->GetSize(), m_TrackerNavigationData->GetPosition());
302 }
303 
305 {
306  if (m_DataStorage.IsNull()) { return false; } //here the widget should simply do nothing (for backward compatibility)
307  else if ( m_ImageFiducialsNode.IsNull() ||
308  m_TrackerFiducialsNode.IsNull()
309  ) {MITK_WARN << "Registration not correctly initialized"; return false;}
310  else {return true;}
311 }
312 
314 {
315  //Check for initialization
316  if (!CheckRegistrationInitialization()) return;
317 
318  /* retrieve fiducials */
319  mitk::PointSet::Pointer imageFiducials = dynamic_cast<mitk::PointSet*>(m_ImageFiducialsNode->GetData());
320  mitk::PointSet::Pointer trackerFiducials = dynamic_cast<mitk::PointSet*>(m_TrackerFiducialsNode->GetData());
321  if (trackerFiducials->GetSize() != imageFiducials->GetSize())
322  {
323  MITK_WARN << "Not the same number of fiducials, cannot register";
324  return;
325  }
326  else if (trackerFiducials->GetSize() < 3)
327  {
328  MITK_WARN << "Need at least 3 fiducials, cannot register";
329  return;
330  }
331 
332  //############### conversion to vtk data types (we will use the vtk landmark based transform) ##########################
333  //convert point sets to vtk poly data
334  vtkSmartPointer<vtkPoints> sourcePoints = vtkSmartPointer<vtkPoints>::New();
335  vtkSmartPointer<vtkPoints> targetPoints = vtkSmartPointer<vtkPoints>::New();
336  for (int i = 0; i<imageFiducials->GetSize(); i++)
337  {
338  double point[3] = { imageFiducials->GetPoint(i)[0], imageFiducials->GetPoint(i)[1], imageFiducials->GetPoint(i)[2] };
339  sourcePoints->InsertNextPoint(point);
340  double point_targets[3] = { trackerFiducials->GetPoint(i)[0], trackerFiducials->GetPoint(i)[1], trackerFiducials->GetPoint(i)[2] };
341  targetPoints->InsertNextPoint(point_targets);
342  }
343 
344  //########################### here, the actual transform is computed ##########################
345  //compute transform
346  vtkSmartPointer<vtkLandmarkTransform> transform = vtkSmartPointer<vtkLandmarkTransform>::New();
347  transform->SetSourceLandmarks(sourcePoints);
348  transform->SetTargetLandmarks(targetPoints);
349  transform->SetModeToRigidBody();
350  transform->Modified();
351  transform->Update();
352  //compute FRE of transform
353 
354  double FRE = mitk::StaticIGTHelperFunctions::ComputeFRE(imageFiducials, trackerFiducials, transform);
355  this->SetQualityDisplayText("FRE: " + QString::number(FRE) + " mm");
356 
357  //#############################################################################################
358 
359  //############### conversion back to itk/mitk data types ##########################
360  //convert from vtk to itk data types
361  itk::Matrix<float, 3, 3> rotationFloat = itk::Matrix<float, 3, 3>();
362  itk::Vector<float, 3> translationFloat = itk::Vector<float, 3>();
363  itk::Matrix<double, 3, 3> rotationDouble = itk::Matrix<double, 3, 3>();
364  itk::Vector<double, 3> translationDouble = itk::Vector<double, 3>();
365 
366  vtkSmartPointer<vtkMatrix4x4> m = transform->GetMatrix();
367  for (int k = 0; k<3; k++) for (int l = 0; l<3; l++)
368  {
369  rotationFloat[k][l] = m->GetElement(k, l);
370  rotationDouble[k][l] = m->GetElement(k, l);
371 
372  }
373  for (int k = 0; k<3; k++)
374  {
375  translationFloat[k] = m->GetElement(k, 3);
376  translationDouble[k] = m->GetElement(k, 3);
377  }
378  //create affine transform 3D surface
379  mitk::AffineTransform3D::Pointer mitkTransform = mitk::AffineTransform3D::New();
380  mitkTransform->SetMatrix(rotationDouble);
381  mitkTransform->SetOffset(translationDouble);
382  //#############################################################################################
383 
384  //############### object is transformed ##########################
385  //save transform
386  m_T_ObjectReg = mitk::NavigationData::New(mitkTransform); // this is stored in a member because it is needed for permanent registration later on
387 
388  //transform surface/image
389  //only move image if we have one. Sometimes, this widget is used just to register point sets without images.
390  if (m_ImageNode.IsNotNull())
391  {
392  //first we have to store the original ct image transform to compose it with the new transform later
393  mitk::AffineTransform3D::Pointer imageTransform = m_ImageNode->GetData()->GetGeometry()->GetIndexToWorldTransform();
394  imageTransform->Compose(mitkTransform);
395  mitk::AffineTransform3D::Pointer newImageTransform = mitk::AffineTransform3D::New(); //create new image transform... setting the composed directly leads to an error
396  itk::Matrix<mitk::ScalarType, 3, 3> rotationFloatNew = imageTransform->GetMatrix();
397  itk::Vector<mitk::ScalarType, 3> translationFloatNew = imageTransform->GetOffset();
398  newImageTransform->SetMatrix(rotationFloatNew);
399  newImageTransform->SetOffset(translationFloatNew);
400  m_ImageNode->GetData()->GetGeometry()->SetIndexToWorldTransform(newImageTransform);
401  }
402 
403  //If this option is set, each point will be transformed and the acutal coordinates of the points change.
404  if (this->m_Controls->m_MoveImagePoints->isChecked())
405  {
406  mitk::PointSet* pointSet_orig = dynamic_cast<mitk::PointSet*>(m_ImageFiducialsNode->GetData());
407  mitk::PointSet::Pointer pointSet_moved = mitk::PointSet::New();
408 
409  for (int i = 0; i < pointSet_orig->GetSize(); i++)
410  {
411  pointSet_moved->InsertPoint(mitkTransform->TransformPoint(pointSet_orig->GetPoint(i)));
412  }
413 
414  pointSet_orig->Clear();
415  for (int i = 0; i < pointSet_moved->GetSize(); i++)
416  pointSet_orig->InsertPoint(pointSet_moved->GetPoint(i));
417  }
418 
419  //Do a global reinit
421 }
static Pointer New()
void HideTrackingFiducialButton(bool on)
show or hide "Add tracking fiducial" button in the UI
float k(1.0)
bool UseICPIsChecked()
returns true if automatic correspondences search is activated else false
WidgetAppearanceMode
enumeration to specify the appearance of the widget. &#39;FIDUCIALMODE&#39; is likely to be used for (trackin...
static Pointer New()
void AdjustButtonSpacing()
Rearrange spacing when buttons are turned on or off.
#define MITK_DEBUG
Definition: mitkLogMacros.h:22
void HideImageFiducialButton(bool on)
show or hide "Add image fiducial" button in the UI
void PerformFiducialRegistration()
signal if all fiducial were added and registration can be performed
Ui::QmitkFiducialRegistrationWidget * m_Controls
gui widget
Controls the selection of the slice the associated BaseRenderer will display.
void SetTargetLandmarkName(QString targetLandmarkName)
Specify the name of the source landmarks. Will be used for label and button.
void SetImageFiducialsNode(mitk::DataNode::Pointer imageFiducialsNode)
specify data tree node for the image fiducials
mitk::NavigationData::Pointer m_TrackerNavigationData
virtual int GetSize(unsigned int t=0) const
returns the current size of the point-list
void DisableEditButtonRegistrationImagePoints(bool)
Disables the edit button of the widget RegistrationImagePoints if the activated variable is true...
void SetTrackerFiducialsNode(mitk::DataNode::Pointer trackerFiducialsNode)
specify data tree node for the tracker fiducials
#define MITK_WARN
Definition: mitkLogMacros.h:19
void SetMultiWidget(QmitkStdMultiWidget *multiWidget)
(Deprecated method. Multiwidget is not required any more.) Set the default stdMultiWidget (needed for...
Data structure which stores a set of points. Superclass of mitk::Mesh.
Definition: mitkPointSet.h:75
The &#39;QmitkStdMultiWidget&#39; is a &#39;QmitkAbstractMultiWidget&#39; that is used to display multiple render win...
void HideContinousRegistrationRadioButton(bool on)
show or hide "hybrid continuous Fiducial Registration" radio button in the UI
void setDataStorage(mitk::DataStorage::Pointer d)
static Pointer New()
static RenderingManager * GetInstance()
static double ComputeFRE(mitk::PointSet::Pointer imageFiducials, mitk::PointSet::Pointer realWorldFiducials, vtkSmartPointer< vtkLandmarkTransform > transform=nullptr)
Computes the fiducial registration error out of two sets of fiducials. The two sets must have the sam...
void AddedTrackingFiducial()
signal if a world instrument position was added to a tracking space fiducial
void InsertPoint(PointIdentifier id, PointType point, int t=0)
Set the given point in world coordinate system into the itkPointSet.
void FindFiducialCorrespondences(bool on)
signal if automatic correspondences search is toggled
void SetSourceLandmarkName(QString sourceLandmarkName)
Specify the name of the source landmarks. Will be used for label and button.
void SetQualityDisplayText(QString text)
sets specific text on the UI (useful to display FRE/TRE...)
virtual void Clear()
Calls ClearData() and InitializeEmpty();.
void setTrackerNavigationData(mitk::NavigationData::Pointer t)
mitk::DataNode::Pointer GetTrackerFiducialsNode()
returns data tree node for the tracker fiducials
void SetWidgetAppearanceMode(WidgetAppearanceMode widgetMode)
set the appearance mode of this widget &#39;FIDUCIALMODE&#39; adapts the widget for (tracking) fiducial based...
void AddedImageFiducial()
signal if an image position was added to a image space fiducial
void HideFiducialRegistrationGroupBox()
show or hide "Fiducial Registration method" groupbox in the UI, depending on the visibility of the ra...
PointType GetPoint(PointIdentifier id, int t=0) const
Get the point with ID id in world coordinates.
void setImageNode(mitk::DataNode::Pointer i)
void HideUseICPRegistrationCheckbox(bool on)
show or hide "Find fiducial correspondences (needs 6+ fiducial pairs)" check box in the UI ...
virtual void InitializeViewsByBoundingObjects(const DataStorage *)
Initializes the renderwindows by the aggregated geometry of all objects that are held in the data sto...
void HideStaticRegistrationRadioButton(bool on)
show or hide "static Fiducial Registration" radio button in the UI
void AddSliceNavigationController(mitk::SliceNavigationController *snc)
add the slice navigation controller to be used to move the crosshair to the actual point position ...
mitk::DataNode::Pointer GetImageFiducialsNode()
returns data tree node for the image fiducials
void DisableEditButtonRegistrationTrackingPoints(bool)
Disables the edit button of the widget RegistrationTrackingPoints if the activated variable is true...