Medical Imaging Interaction Toolkit  2016.11.0
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,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
18 
19 #include <vtkTransform.h>
20 #include <vtkTransformPolyDataFilter.h>
21 #include <vtkAppendPolyData.h>
22 #include <vtkPoints.h>
23 #include <vtkLandmarkTransform.h>
25 
26 #include <mitkRenderingManager.h>
27 
28 #define FRW_LOG MITK_INFO("Fiducial Registration Widget")
29 #define FRW_WARN MITK_WARN("Fiducial Registration Widget")
30 #define FRW_DEBUG MITK_DEBUG("Fiducial Registration Widget")
31 
32 /* VIEW MANAGEMENT */
34 : QWidget(parent), m_Controls(NULL),m_MultiWidget(NULL), m_ImageFiducialsNode(NULL), m_TrackerFiducialsNode(NULL)
35 {
36  CreateQtPartControl(this);
37 }
38 
39 
41 {
42  m_Controls = NULL;
43 
44  //clean up data nodes
45  if (m_DataStorage.IsNotNull())
46  {
49  }
50 }
51 
52 
54 {
55  if (!m_Controls)
56  {
57  // create GUI widgets
58  m_Controls = new Ui::QmitkFiducialRegistrationWidget;
59  m_Controls->setupUi(parent);
60 
61  // hide additional image fiducial button
62  m_Controls->m_AddImageFiducialBtn->setHidden(true);
63 
64  m_Controls->m_spaceHolderGroupBox->setStyleSheet("QGroupBox {border: 0px transparent;}");
65  m_Controls->m_spaceHolderGroupBox2->setStyleSheet("QGroupBox {border: 0px transparent;}");
66 
67  this->CreateConnections();
68  }
69 }
70 
71 
73 {
74  connect( (QObject*)(m_Controls->m_AddTrackingFiducialBtn), SIGNAL(clicked()), this, SIGNAL(AddedTrackingFiducial()) );
75  connect((QObject*)(m_Controls->m_AddTrackingFiducialBtn), SIGNAL(clicked()), this, SLOT(AddTrackerPoint()));
76  connect( (QObject*)(m_Controls->m_AddImageFiducialBtn), SIGNAL(clicked()), this, SIGNAL(AddedImageFiducial()) );
77  connect( (QObject*)(m_Controls->m_RegisterFiducialsBtn), SIGNAL(clicked()), this, SIGNAL(PerformFiducialRegistration()) );
78  connect((QObject*)(m_Controls->m_RegisterFiducialsBtn), SIGNAL(clicked()), this, SLOT(Register()));
79  connect( (QObject*)(m_Controls->m_UseICPRegistration), SIGNAL(toggled(bool)), this, SIGNAL(FindFiducialCorrespondences(bool)) );
80 
81  //unselects the edit button of the other widget if one is selected
82  connect( (QObject*)(m_Controls->m_RegistrationImagePoints), SIGNAL(EditPointSets(bool)), this, SLOT(DisableEditButtonRegistrationTrackingPoints(bool)));
83  connect( (QObject*)(m_Controls->m_RegistrationTrackingPoints), SIGNAL(EditPointSets(bool)), this, SLOT(DisableEditButtonRegistrationImagePoints(bool)));
84 }
85 
87 {
88 if (activated) m_Controls->m_RegistrationImagePoints->UnselectEditButton();
89 }
91 {
92 if (activated) m_Controls->m_RegistrationTrackingPoints->UnselectEditButton();
93 }
94 
96 {
97  if (widgetMode==LANDMARKMODE)
98  {
102  this->HideUseICPRegistrationCheckbox(true);
103  this->HideImageFiducialButton(false);
104  this->m_Controls->sourceLandmarksGroupBox->setTitle("Target/Reference landmarks");
105  this->m_Controls->targetLandmarksGroupBox->setTitle("Source Landmarks");
106  this->m_Controls->m_AddImageFiducialBtn->setText("Add target landmark");
107  this->m_Controls->m_AddTrackingFiducialBtn->setText("Add source landmark");
108  }
109  else if (widgetMode==FIDUCIALMODE)
110  {
114  this->HideUseICPRegistrationCheckbox(false);
115  this->HideImageFiducialButton(true);
116  this->m_Controls->sourceLandmarksGroupBox->setTitle("Image fiducials");
117  this->m_Controls->targetLandmarksGroupBox->setTitle("OR fiducials");
118  this->m_Controls->m_AddImageFiducialBtn->setText("Add image fiducial");
119  this->m_Controls->m_AddTrackingFiducialBtn->setText("Add current instrument position");
120  }
121 }
122 
124 {
125  if (text == NULL)
126  return;
127  m_Controls->m_RegistrationQualityDisplay->setText(text); // set text on the QLabel
128 }
129 
131 {
132  if(m_Controls->m_UseICPRegistration->isChecked())
133  return true;
134  else
135  return false;
136 }
137 
139 {
140  if(imageFiducialsNode.IsNull())
141  {
142  FRW_WARN<< "tracker fiducial node is NULL";
143  return;
144  }
145  m_Controls->m_RegistrationImagePoints->SetPointSetNode(imageFiducialsNode); // pass node to pointListWidget
146  if(m_MultiWidget == NULL)
147  {
148  MITK_DEBUG<< "stdMultiWidget is NULL";
149  return;
150  }
151  m_Controls->m_RegistrationImagePoints->SetMultiWidget(m_MultiWidget); // pass multiWidget to pointListWidget
152 }
153 
155 {
156  if(trackerFiducialsNode.IsNull())
157  {
158  FRW_WARN<< "tracker fiducial node is NULL";
159  return;
160  }
161  m_Controls->m_RegistrationTrackingPoints->SetPointSetNode(trackerFiducialsNode); // pass node to pointListWidget
162  if(m_MultiWidget == NULL)
163  {
164  MITK_DEBUG<< "stdMultiWidget is NULL";
165  return;
166  }
167  m_Controls->m_RegistrationTrackingPoints->SetMultiWidget(m_MultiWidget); // pass multiWidget to pointListWidget
168 }
169 
171 {
172  m_MultiWidget=multiWidget;
173 }
174 
176 {
177  m_Controls->m_RegistrationTrackingPoints->AddSliceNavigationController(snc);
178  m_Controls->m_RegistrationImagePoints->AddSliceNavigationController(snc);
179 }
180 
182 {
183  return m_ImageFiducialsNode;
184 }
185 
187 {
188  return m_TrackerFiducialsNode;
189 }
190 
192 {
193  m_Controls->m_rbStaticRegistration->setHidden(on);
195 }
196 
198 {
199  m_Controls->m_rbContinousRegistration->setHidden(on);
201 }
202 
204 {
205  if (m_Controls->m_rbStaticRegistration->isHidden() && m_Controls->m_rbContinousRegistration->isHidden())
206  {
207  m_Controls->m_gbFiducialRegistration->setHidden(true);
208  }
209  else
210  {
211  m_Controls->m_gbFiducialRegistration->setHidden(false);
212  }
213 }
214 
216 {
217  m_Controls->m_UseICPRegistration->setHidden(on);
218 }
219 
221 {
222  m_Controls->m_AddImageFiducialBtn->setHidden(on);
224 
225 }
226 
228 {
229  m_Controls->m_AddTrackingFiducialBtn->setHidden(on);
231 }
232 
234 {
235  if (m_Controls->m_AddImageFiducialBtn->isHidden() && m_Controls->m_AddTrackingFiducialBtn->isHidden())
236  {
237  m_Controls->m_spaceHolderGroupBox->setHidden(true);
238  m_Controls->m_spaceHolderGroupBox2->setHidden(true);
239  }
240  else
241  {
242  m_Controls->m_spaceHolderGroupBox->setHidden(false);
243  m_Controls->m_spaceHolderGroupBox2->setHidden(false);
244  }
245 }
246 
248 {
249  QString groupBoxTitle = sourceLandmarkName;
250  groupBoxTitle.append(" Landmarks");
251  m_Controls->sourceLandmarksGroupBox->setTitle(groupBoxTitle);
252  QString buttonText = "Add ";
253  buttonText.append(sourceLandmarkName);
254  buttonText.append(" Landmark");
255  m_Controls->m_AddImageFiducialBtn->setText(buttonText);
256 }
257 
259 {
260  QString groupBoxTitle = targetLandmarkName;
261  groupBoxTitle.append(" Landmarks");
262  m_Controls->targetLandmarksGroupBox->setTitle(groupBoxTitle);
263  QString buttonText = "Add ";
264  buttonText.append(targetLandmarkName);
265  buttonText.append(" Landmark");
266  m_Controls->m_AddTrackingFiducialBtn->setText(buttonText);
267 }
268 
270 {
271  m_ImageNode = i;
272 }
273 
275 {
277 }
278 
280 {
281  m_DataStorage = d;
282 
283  mitk::DataNode::Pointer ImageFiducialsNode = mitk::DataNode::New();
285  ImageFiducialsNode->SetData(imagePointSet);
286  ImageFiducialsNode->SetName("Image Point Set");
287  m_DataStorage->Add(ImageFiducialsNode);
288  this->SetImageFiducialsNode(ImageFiducialsNode);
289  m_ImageFiducialsNode = ImageFiducialsNode;
290 
291  mitk::DataNode::Pointer TrackerFiducialsNode = mitk::DataNode::New();
292  mitk::PointSet::Pointer trackerPointSet = mitk::PointSet::New();
293  TrackerFiducialsNode->SetData(trackerPointSet);
294  TrackerFiducialsNode->SetName("Tracker Point Set");
295  m_DataStorage->Add(TrackerFiducialsNode);
296  this->SetTrackerFiducialsNode(TrackerFiducialsNode);
297  m_TrackerFiducialsNode = TrackerFiducialsNode;
298 }
299 
301 {
302  if (m_DataStorage.IsNull()) { return ; } //here the widget should simply do nothing (for backward compatibility)
303  else if (m_TrackerNavigationData.IsNull() || m_TrackerFiducialsNode.IsNull()) { MITK_WARN << "Tracker node not correctly initialized"; return; }
304  mitk::PointSet::Pointer ps = dynamic_cast<mitk::PointSet*>(m_TrackerFiducialsNode->GetData());
305  ps->InsertPoint(ps->GetSize(), m_TrackerNavigationData->GetPosition());
306 }
307 
309 {
310  if (m_DataStorage.IsNull()) { return false; } //here the widget should simply do nothing (for backward compatibility)
311  else if ( m_ImageFiducialsNode.IsNull() ||
312  m_TrackerFiducialsNode.IsNull()
313  ) {MITK_WARN << "Registration not correctly initialized"; return false;}
314  else {return true;}
315 }
316 
318 {
319  //Check for initialization
320  if (!CheckRegistrationInitialization()) return;
321 
322  /* retrieve fiducials */
323  mitk::PointSet::Pointer imageFiducials = dynamic_cast<mitk::PointSet*>(m_ImageFiducialsNode->GetData());
324  mitk::PointSet::Pointer trackerFiducials = dynamic_cast<mitk::PointSet*>(m_TrackerFiducialsNode->GetData());
325  if (trackerFiducials->GetSize() != imageFiducials->GetSize())
326  {
327  MITK_WARN << "Not the same number of fiducials, cannot register";
328  return;
329  }
330  else if (trackerFiducials->GetSize() < 3)
331  {
332  MITK_WARN << "Need at least 3 fiducials, cannot register";
333  return;
334  }
335 
336  //############### conversion to vtk data types (we will use the vtk landmark based transform) ##########################
337  //convert point sets to vtk poly data
338  vtkSmartPointer<vtkPoints> sourcePoints = vtkSmartPointer<vtkPoints>::New();
339  vtkSmartPointer<vtkPoints> targetPoints = vtkSmartPointer<vtkPoints>::New();
340  for (int i = 0; i<imageFiducials->GetSize(); i++)
341  {
342  double point[3] = { imageFiducials->GetPoint(i)[0], imageFiducials->GetPoint(i)[1], imageFiducials->GetPoint(i)[2] };
343  sourcePoints->InsertNextPoint(point);
344  double point_targets[3] = { trackerFiducials->GetPoint(i)[0], trackerFiducials->GetPoint(i)[1], trackerFiducials->GetPoint(i)[2] };
345  targetPoints->InsertNextPoint(point_targets);
346  }
347 
348  //########################### here, the actual transform is computed ##########################
349  //compute transform
350  vtkSmartPointer<vtkLandmarkTransform> transform = vtkSmartPointer<vtkLandmarkTransform>::New();
351  transform->SetSourceLandmarks(sourcePoints);
352  transform->SetTargetLandmarks(targetPoints);
353  transform->SetModeToRigidBody();
354  transform->Modified();
355  transform->Update();
356  //compute FRE of transform
357 
358  double FRE = mitk::StaticIGTHelperFunctions::ComputeFRE(imageFiducials, trackerFiducials, transform);
359  this->SetQualityDisplayText("FRE: " + QString::number(FRE) + " mm");
360 
361  //#############################################################################################
362 
363  //############### conversion back to itk/mitk data types ##########################
364  //convert from vtk to itk data types
365  itk::Matrix<float, 3, 3> rotationFloat = itk::Matrix<float, 3, 3>();
366  itk::Vector<float, 3> translationFloat = itk::Vector<float, 3>();
367  itk::Matrix<double, 3, 3> rotationDouble = itk::Matrix<double, 3, 3>();
368  itk::Vector<double, 3> translationDouble = itk::Vector<double, 3>();
369 
370  vtkSmartPointer<vtkMatrix4x4> m = transform->GetMatrix();
371  for (int k = 0; k<3; k++) for (int l = 0; l<3; l++)
372  {
373  rotationFloat[k][l] = m->GetElement(k, l);
374  rotationDouble[k][l] = m->GetElement(k, l);
375 
376  }
377  for (int k = 0; k<3; k++)
378  {
379  translationFloat[k] = m->GetElement(k, 3);
380  translationDouble[k] = m->GetElement(k, 3);
381  }
382  //create affine transform 3D surface
384  mitkTransform->SetMatrix(rotationDouble);
385  mitkTransform->SetOffset(translationDouble);
386  //#############################################################################################
387 
388  //############### object is transformed ##########################
389  //save transform
390  m_T_ObjectReg = mitk::NavigationData::New(mitkTransform); // this is stored in a member because it is needed for permanent registration later on
391 
392  //transform surface/image
393  //only move image if we have one. Sometimes, this widget is used just to register point sets without images.
394  if (m_ImageNode.IsNotNull())
395  {
396  //first we have to store the original ct image transform to compose it with the new transform later
397  mitk::AffineTransform3D::Pointer imageTransform = m_ImageNode->GetData()->GetGeometry()->GetIndexToWorldTransform();
398  imageTransform->Compose(mitkTransform);
399  mitk::AffineTransform3D::Pointer newImageTransform = mitk::AffineTransform3D::New(); //create new image transform... setting the composed directly leads to an error
400  itk::Matrix<mitk::ScalarType, 3, 3> rotationFloatNew = imageTransform->GetMatrix();
401  itk::Vector<mitk::ScalarType, 3> translationFloatNew = imageTransform->GetOffset();
402  newImageTransform->SetMatrix(rotationFloatNew);
403  newImageTransform->SetOffset(translationFloatNew);
404  m_ImageNode->GetData()->GetGeometry()->SetIndexToWorldTransform(newImageTransform);
405  }
406 
407  //If this option is set, each point will be transformed and the acutal coordinates of the points change.
408  if (this->m_Controls->m_MoveImagePoints->isChecked())
409  {
410  mitk::PointSet* pointSet_orig = dynamic_cast<mitk::PointSet*>(m_ImageFiducialsNode->GetData());
411  mitk::PointSet::Pointer pointSet_moved = mitk::PointSet::New();
412 
413  for (int i = 0; i < pointSet_orig->GetSize(); i++)
414  {
415  pointSet_moved->InsertPoint(mitkTransform->TransformPoint(pointSet_orig->GetPoint(i)));
416  }
417 
418  pointSet_orig->Clear();
419  for (int i = 0; i < pointSet_moved->GetSize(); i++)
420  pointSet_orig->InsertPoint(pointSet_moved->GetPoint(i));
421  }
422 
423  //Do a global reinit
425 }
static Pointer New()
void HideTrackingFiducialButton(bool on)
show or hide "Add tracking fiducial" button in the UI
bool UseICPIsChecked()
returns true if automatic correspondences search is activated else false
itk::SmartPointer< Self > Pointer
WidgetAppearanceMode
enumeration to specify the appearance of the widget. 'FIDUCIALMODE' is likely to be used for (trackin...
virtual int GetSize(unsigned int t=0) const
returns the current size of the point-list
static Pointer New()
void AdjustButtonSpacing()
Rearrange spacing when buttons are turned on or off.
#define MITK_DEBUG
Definition: mitkLogMacros.h:26
PointType GetPoint(PointIdentifier id, int t=0) const
Get the point with ID id in world coordinates.
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
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:23
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:79
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()
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 'FIDUCIALMODE' 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...
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
static double ComputeFRE(mitk::PointSet::Pointer imageFiducials, mitk::PointSet::Pointer realWorldFiducials, vtkSmartPointer< vtkLandmarkTransform > transform=NULL)
Computes the fiducial registration error out of two sets of fiducials. The two sets must have the sam...
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...
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.