MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
QmitkFiducialRegistrationWidget.cpp
Go to the documentation of this file.
1/*============================================================================
2
3The Medical Imaging Interaction Toolkit (MITK)
4
5Copyright (c) German Cancer Research Center (DKFZ)
6All rights reserved.
7
8Use of this source code is governed by a 3-clause BSD license that can be
9found 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{
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{
84if (activated) m_Controls->m_RegistrationImagePoints->UnselectEditButton();
85}
87{
88if (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 {
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
134void QmitkFiducialRegistrationWidget::SetImageFiducialsNode( mitk::DataNode::Pointer imageFiducialsNode )
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<< "MultiWidget is nullptr";
145 return;
146 }
147 m_Controls->m_RegistrationImagePoints->SetMultiWidget(m_MultiWidget); // pass multiWidget to pointListWidget
148}
149
150void QmitkFiducialRegistrationWidget::SetTrackerFiducialsNode( mitk::DataNode::Pointer trackerFiducialsNode )
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<< "MultiWidget is nullptr";
161 return;
162 }
163 m_Controls->m_RegistrationTrackingPoints->SetMultiWidget(m_MultiWidget); // pass multiWidget to pointListWidget
164}
165
166void QmitkFiducialRegistrationWidget::SetMultiWidget( QmitkAbstractMultiWidget* multiWidget )
167{
168 m_MultiWidget=multiWidget;
169}
170
172{
173 m_Controls->m_RegistrationTrackingPoints->AddSliceNavigationController(snc);
174 m_Controls->m_RegistrationImagePoints->AddSliceNavigationController(snc);
175}
176
181
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
275void QmitkFiducialRegistrationWidget::setDataStorage(mitk::DataStorage::Pointer d)
276{
277 m_DataStorage = d;
278
279 mitk::DataNode::Pointer ImageFiducialsNode = mitk::DataNode::New();
280 mitk::PointSet::Pointer imagePointSet = mitk::PointSet::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() ||
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
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
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
420 mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage);
421}
void AddedImageFiducial()
signal if an image position was added to a image space fiducial
mitk::NavigationData::Pointer m_TrackerNavigationData
void HideContinousRegistrationRadioButton(bool on)
show or hide "hybrid continuous Fiducial Registration" radio button in the UI
void DisableEditButtonRegistrationTrackingPoints(bool)
Disables the edit button of the widget RegistrationTrackingPoints if the activated variable is true.
mitk::DataNode::Pointer GetImageFiducialsNode()
returns data tree node for the image fiducials
void SetMultiWidget(QmitkAbstractMultiWidget *multiWidget)
(Deprecated method. Multiwidget is not required any more.) Set the default MultiWidget (needed for th...
void SetSourceLandmarkName(QString sourceLandmarkName)
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
void HideStaticRegistrationRadioButton(bool on)
show or hide "static Fiducial Registration" radio button in the UI
Ui::QmitkFiducialRegistrationWidget * m_Controls
gui widget
void FindFiducialCorrespondences(bool on)
signal if automatic correspondences search is toggled
void SetTrackerFiducialsNode(mitk::DataNode::Pointer trackerFiducialsNode)
specify data tree node for the tracker fiducials
void setTrackerNavigationData(mitk::NavigationData::Pointer t)
void AddedTrackingFiducial()
signal if a world instrument position was added to a tracking space fiducial
void HideFiducialRegistrationGroupBox()
show or hide "Fiducial Registration method" groupbox in the UI, depending on the visibility of the ra...
void PerformFiducialRegistration()
signal if all fiducial were added and registration can be performed
void SetWidgetAppearanceMode(WidgetAppearanceMode widgetMode)
set the appearance mode of this widget 'FIDUCIALMODE' adapts the widget for (tracking) fiducial based...
void AddSliceNavigationController(mitk::SliceNavigationController *snc)
add the slice navigation controller to be used to move the crosshair to the actual point position
void SetTargetLandmarkName(QString targetLandmarkName)
Specify the name of the source landmarks. Will be used for label and button.
void setDataStorage(mitk::DataStorage::Pointer d)
void HideTrackingFiducialButton(bool on)
show or hide "Add tracking fiducial" button in the UI
mitk::DataNode::Pointer GetTrackerFiducialsNode()
returns data tree node for the tracker fiducials
void HideUseICPRegistrationCheckbox(bool on)
show or hide "Find fiducial correspondences (needs 6+ fiducial pairs)" check box in the UI
WidgetAppearanceMode
enumeration to specify the appearance of the widget. 'FIDUCIALMODE' is likely to be used for (trackin...
void AdjustButtonSpacing()
Rearrange spacing when buttons are turned on or off.
void HideImageFiducialButton(bool on)
show or hide "Add image fiducial" button in the UI
bool UseICPIsChecked()
returns true if automatic correspondences search is activated else false
void SetQualityDisplayText(QString text)
sets specific text on the UI (useful to display FRE/TRE...)
void DisableEditButtonRegistrationImagePoints(bool)
Disables the edit button of the widget RegistrationImagePoints if the activated variable is true.
MITKIGTBASE_EXPORT 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...