MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
QmitkUSNavigationStepCtUsRegistration.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#include "ui_QmitkUSNavigationStepCtUsRegistration.h"
15
16#include <QMessageBox>
17
21
22
23
24#include <mitkNodePredicateNot.h>
25#include <mitkNodePredicateProperty.h>
26#include <mitkLabelSetImage.h>
27#include "mitkProperties.h"
28#include <mitkImage.h>
29#include <mitkImageCast.h>
30
31#include <mitkRenderingManager.h>
33
34#include <vtkLandmarkTransform.h>
35#include <vtkPoints.h>
36
37#include <itkImageRegionIterator.h>
38#include <itkGeometryUtilities.h>
39#include <mitkImagePixelReadAccessor.h>
40
41#include <itkZeroCrossingImageFilter.h>
42#include <itkSimpleContourExtractorImageFilter.h>
43#include <itkCannyEdgeDetectionImageFilter.h>
44
45static const int NUMBER_FIDUCIALS_NEEDED = 8;
46
50 m_PerformingGroundTruthProtocolEvaluation(false),
51 m_FloatingImageToUltrasoundRegistrationFilter(nullptr),
52 m_FreezeCombinedModality(false)
53{
56 this->CreateQtPartControl(this);
57}
58
59
64
66{
67 MITK_INFO << "OnStartStep()";
68 return true;
69}
70
72{
73 MITK_INFO << "OnStopStep()";
74 return true;
75}
76
78{
79 MITK_INFO << "OnFinishStep()";
80 return true;
81}
82
84{
85 MITK_INFO << "OnActivateStep()";
86 ui->floatingImageComboBox->SetDataStorage(this->GetDataStorage());
87 ui->ctImagesToChooseComboBox->SetDataStorage(this->GetDataStorage());
88 ui->segmentationComboBox->SetDataStorage(this->GetDataStorage());
89 ui->selectedSurfaceComboBox->SetDataStorage(this->GetDataStorage());
90 ui->pointSetComboBox->SetDataStorage(this->GetDataStorage());
91 m_FloatingImageToUltrasoundRegistrationFilter =
92 mitk::FloatingImageToUltrasoundRegistrationFilter::New();
93 return true;
94}
95
97{
98 MITK_INFO << "OnDeactivateStep()";
99 return true;
100}
101
103{
104 if (m_NavigationDataSource.IsNull()) { return; }
105
106 m_NavigationDataSource->Update();
107 m_FloatingImageToUltrasoundRegistrationFilter->Update();
108}
109
111{
112 Q_UNUSED(settingsNode);
113}
114
116{
117 return "CT-to-US registration";
118}
119
124
126{
127 mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetCombinedModality(false);
128 if (combinedModality.IsNotNull())
129 {
130 m_NavigationDataSource = combinedModality->GetNavigationDataSource();
131 }
132
133}
134
136{
137 m_ImageDimension[0] = 0;
138 m_ImageDimension[1] = 0;
139 m_ImageDimension[2] = 0;
140
141 m_ImageSpacing[0] = 1;
142 m_ImageSpacing[1] = 1;
143 m_ImageSpacing[2] = 1;
144}
145
147{
148 m_ImageDimension[0] = image->GetDimension(0);
149 m_ImageDimension[1] = image->GetDimension(1);
150 m_ImageDimension[2] = image->GetDimension(2);
151
152 m_ImageSpacing[0] = image->GetGeometry()->GetSpacing()[0];
153 m_ImageSpacing[1] = image->GetGeometry()->GetSpacing()[1];
154 m_ImageSpacing[2] = image->GetGeometry()->GetSpacing()[2];
155}
156
158{
159 if (m_FloatingImage.IsNull())
160 {
161 return 0.0;
162 }
163
164 MITK_INFO << "ImageSpacing = " << m_ImageSpacing;
165 return m_ImageSpacing[0] * m_ImageSpacing[1] * m_ImageSpacing[2];
166}
167
169{
170 return 1.333333333 * 3.141592 * (radius * radius * radius);
171}
172
174{
175 if (m_FloatingImage.IsNull())
176 {
177 return false;
178 }
179
180 ImageType::Pointer itkImage1 = ImageType::New();
181 mitk::CastToItkImage(m_FloatingImage, itkImage1);
182
184
185 m_ThresholdFilter->SetInput(itkImage1);
186 m_LaplacianFilter1->SetInput(m_ThresholdFilter->GetOutput());
187 m_LaplacianFilter2->SetInput(m_LaplacianFilter1->GetOutput());
188 m_BinaryThresholdFilter->SetInput(m_LaplacianFilter2->GetOutput());
189 m_HoleFillingFilter->SetInput(m_BinaryThresholdFilter->GetOutput());
190 m_BinaryImageToShapeLabelMapFilter->SetInput(m_HoleFillingFilter->GetOutput());
191 m_BinaryImageToShapeLabelMapFilter->Update();
192
193 ImageType::Pointer binaryImage = ImageType::New();
194 binaryImage = m_HoleFillingFilter->GetOutput();
195
196 this->EliminateTooSmallLabeledObjects(binaryImage);
197 //mitk::CastToMitkImage(binaryImage, m_FloatingImage);
198 return true;
199}
200
202{
203 //Initialize threshold filters
204 m_ThresholdFilter = itk::ThresholdImageFilter<ImageType>::New();
205 m_ThresholdFilter->SetOutsideValue(0);
206 m_ThresholdFilter->SetLower(500);
207 m_ThresholdFilter->SetUpper(3200);
208
209 //Initialize binary threshold filter 1
210 m_BinaryThresholdFilter = BinaryThresholdImageFilterType::New();
211 m_BinaryThresholdFilter->SetOutsideValue(0);
212 m_BinaryThresholdFilter->SetInsideValue(1);
213 m_BinaryThresholdFilter->SetLowerThreshold(350);
214 m_BinaryThresholdFilter->SetUpperThreshold(10000);
215
216 //Initialize laplacian recursive gaussian image filter
217 m_LaplacianFilter1 = LaplacianRecursiveGaussianImageFilterType::New();
218 m_LaplacianFilter2 = LaplacianRecursiveGaussianImageFilterType::New();
219
220 //Initialize binary hole filling filter
221 m_HoleFillingFilter = VotingBinaryIterativeHoleFillingImageFilterType::New();
222 VotingBinaryIterativeHoleFillingImageFilterType::InputSizeType radius;
223 radius.Fill(1);
224 m_HoleFillingFilter->SetRadius(radius);
225 m_HoleFillingFilter->SetBackgroundValue(0);
226 m_HoleFillingFilter->SetForegroundValue(1);
227 m_HoleFillingFilter->SetMaximumNumberOfIterations(5);
228
229 //Initialize binary image to shape label map filter
230 m_BinaryImageToShapeLabelMapFilter = BinaryImageToShapeLabelMapFilterType::New();
231 m_BinaryImageToShapeLabelMapFilter->SetInputForegroundValue(1);
232}
233
235{
236 switch (ui->fiducialMarkerConfigurationComboBox->currentIndex())
237 {
238 // case 0 is equal to fiducial marker configuration A (10mm distance)
239 case 0:
240 return 12.07;
241
242 // case 1 is equal to fiducial marker configuration B (15mm distance)
243 case 1:
244 return 18.105;
245
246 // case 2 is equal to fiducial marker configuration C (20mm distance)
247 case 2:
248 return 24.14;
249 }
250 return 0.0;
251}
252
254{
255 switch (ui->fiducialMarkerConfigurationComboBox->currentIndex())
256 {
257 // case 0 is equal to fiducial marker configuration A (10mm distance)
258 case 0:
259 return 12.07;
260
261 // case 1 is equal to fiducial marker configuration B (15mm distance)
262 case 1:
263 return 18.105;
264
265 // case 2 is equal to fiducial marker configuration C (20mm distance)
266 case 2:
267 return 24.14;
268 }
269 return 0.0;
270}
271
273{
274 switch (ui->fiducialMarkerConfigurationComboBox->currentIndex())
275 {
276 // case 0 is equal to fiducial marker configuration A (10mm distance)
277 case 0:
278 return 15.73;
279
280 // case 1 is equal to fiducial marker configuration B (15mm distance)
281 case 1:
282 return 23.595;
283
284 // case 2 is equal to fiducial marker configuration C (20mm distance)
285 case 2:
286 return 31.46;
287 }
288 return 0.0;
289}
290
292{
293 switch (ui->fiducialMarkerConfigurationComboBox->currentIndex())
294 {
295 // case 0 is equal to fiducial marker configuration A (10mm distance)
296 case 0:
297 return 10.0;
298
299 // case 1 is equal to fiducial marker configuration B (15mm distance)
300 case 1:
301 return 15.0;
302
303 // case 2 is equal to fiducial marker configuration C (20mm distance)
304 case 2:
305 return 20.0;
306 }
307 return 0.0;
308}
309
311{
312 if (m_MarkerModelCoordinateSystemPointSet.IsNull())
313 {
314 m_MarkerModelCoordinateSystemPointSet = mitk::PointSet::New();
315 }
316 else
317 {
318 m_MarkerModelCoordinateSystemPointSet->Clear();
319 }
320
321 mitk::Point3D fiducial1;
322 mitk::Point3D fiducial2;
323 mitk::Point3D fiducial3;
324 mitk::Point3D fiducial4;
325 mitk::Point3D fiducial5;
326 mitk::Point3D fiducial6;
327 mitk::Point3D fiducial7;
328 mitk::Point3D fiducial8;
329
330
331
332 switch (ui->fiducialMarkerConfigurationComboBox->currentIndex())
333 {
334 // case 0 is equal to fiducial marker configuration A (10mm distance)
335 case 0:
336 fiducial1[0] = 0;
337 fiducial1[1] = 0;
338 fiducial1[2] = 0;
339
340 fiducial2[0] = 0;
341 fiducial2[1] = 10;
342 fiducial2[2] = 0;
343
344 fiducial3[0] = 10;
345 fiducial3[1] = 0;
346 fiducial3[2] = 0;
347
348 fiducial4[0] = 20;
349 fiducial4[1] = 20;
350 fiducial4[2] = 0;
351
352 fiducial5[0] = 0;
353 fiducial5[1] = 20;
354 fiducial5[2] = 10;
355
356 fiducial6[0] = 10;
357 fiducial6[1] = 20;
358 fiducial6[2] = 10;
359
360 fiducial7[0] = 20;
361 fiducial7[1] = 10;
362 fiducial7[2] = 10;
363
364 fiducial8[0] = 20;
365 fiducial8[1] = 0;
366 fiducial8[2] = 10;
367 break;
368 // case 1 is equal to fiducial marker configuration B (15mm distance)
369 case 1:
370 fiducial1[0] = 0;
371 fiducial1[1] = 0;
372 fiducial1[2] = 0;
373
374 fiducial2[0] = 0;
375 fiducial2[1] = 15;
376 fiducial2[2] = 0;
377
378 fiducial3[0] = 15;
379 fiducial3[1] = 0;
380 fiducial3[2] = 0;
381
382 fiducial4[0] = 30;
383 fiducial4[1] = 30;
384 fiducial4[2] = 0;
385
386 fiducial5[0] = 0;
387 fiducial5[1] = 30;
388 fiducial5[2] = 15;
389
390 fiducial6[0] = 15;
391 fiducial6[1] = 30;
392 fiducial6[2] = 15;
393
394 fiducial7[0] = 30;
395 fiducial7[1] = 15;
396 fiducial7[2] = 15;
397
398 fiducial8[0] = 30;
399 fiducial8[1] = 0;
400 fiducial8[2] = 15;
401 break;
402 // case 2 is equal to fiducial marker configuration C (20mm distance)
403 case 2:
404 fiducial1[0] = 0;
405 fiducial1[1] = 0;
406 fiducial1[2] = 0;
407
408 fiducial2[0] = 0;
409 fiducial2[1] = 20;
410 fiducial2[2] = 0;
411
412 fiducial3[0] = 20;
413 fiducial3[1] = 0;
414 fiducial3[2] = 0;
415
416 fiducial4[0] = 40;
417 fiducial4[1] = 40;
418 fiducial4[2] = 0;
419
420 fiducial5[0] = 0;
421 fiducial5[1] = 40;
422 fiducial5[2] = 20;
423
424 fiducial6[0] = 20;
425 fiducial6[1] = 40;
426 fiducial6[2] = 20;
427
428 fiducial7[0] = 40;
429 fiducial7[1] = 20;
430 fiducial7[2] = 20;
431
432 fiducial8[0] = 40;
433 fiducial8[1] = 0;
434 fiducial8[2] = 20;
435 break;
436 }
437
438 m_MarkerModelCoordinateSystemPointSet->InsertPoint(0, fiducial1);
439 m_MarkerModelCoordinateSystemPointSet->InsertPoint(1, fiducial2);
440 m_MarkerModelCoordinateSystemPointSet->InsertPoint(2, fiducial3);
441 m_MarkerModelCoordinateSystemPointSet->InsertPoint(3, fiducial4);
442 m_MarkerModelCoordinateSystemPointSet->InsertPoint(4, fiducial5);
443 m_MarkerModelCoordinateSystemPointSet->InsertPoint(5, fiducial6);
444 m_MarkerModelCoordinateSystemPointSet->InsertPoint(6, fiducial7);
445 m_MarkerModelCoordinateSystemPointSet->InsertPoint(7, fiducial8);
446
447 /*mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode("Marker Model Coordinate System Point Set");
448 if (node == nullptr)
449 {
450 node = mitk::DataNode::New();
451 node->SetName("Marker Model Coordinate System Point Set");
452 node->SetData(m_MarkerModelCoordinateSystemPointSet);
453 this->GetDataStorage()->Add(node);
454 }
455 else
456 {
457 node->SetData(m_MarkerModelCoordinateSystemPointSet);
458 this->GetDataStorage()->Modified();
459 }*/
460}
461
463{
464
465 m_PointsToTransformGroundTruthProtocol.clear();
466
467 mitk::Point3D point0mm;
468 mitk::Point3D point20mm;
469 mitk::Point3D point40mm;
470 mitk::Point3D point60mm;
471 mitk::Point3D point80mm;
472 mitk::Point3D point100mm;
473
474 point0mm[0] = 0.0;
475 point0mm[1] = 0.0;
476 point0mm[2] = 0.0;
477
478 point20mm[0] = 0.0;
479 point20mm[1] = 0.0;
480 point20mm[2] = 0.0;
481
482 point40mm[0] = 0.0;
483 point40mm[1] = 0.0;
484 point40mm[2] = 0.0;
485
486 point60mm[0] = 0.0;
487 point60mm[1] = 0.0;
488 point60mm[2] = 0.0;
489
490 point80mm[0] = 0.0;
491 point80mm[1] = 0.0;
492 point80mm[2] = 0.0;
493
494 point100mm[0] = 0.0;
495 point100mm[1] = 0.0;
496 point100mm[2] = 0.0;
497
498 m_PointsToTransformGroundTruthProtocol.insert(std::pair<int, mitk::Point3D>(0, point0mm));
499 m_PointsToTransformGroundTruthProtocol.insert(std::pair<int, mitk::Point3D>(20, point20mm));
500 m_PointsToTransformGroundTruthProtocol.insert(std::pair<int, mitk::Point3D>(40, point40mm));
501 m_PointsToTransformGroundTruthProtocol.insert(std::pair<int, mitk::Point3D>(60, point60mm));
502 m_PointsToTransformGroundTruthProtocol.insert(std::pair<int, mitk::Point3D>(80, point80mm));
503 m_PointsToTransformGroundTruthProtocol.insert(std::pair<int, mitk::Point3D>(100, point100mm));
504}
505
507{
509
510 switch (ui->fiducialMarkerConfigurationComboBox->currentIndex())
511 {
512 // case 0 is equal to fiducial marker configuration A (10mm distance)
513 case 0:
514 MITK_WARN << "For this marker configuration (10mm) there does not exist a point to transform.";
515 break;
516 // case 1 is equal to fiducial marker configuration B (15mm distance)
517 case 1:
518 m_PointsToTransformGroundTruthProtocol.at(0)[0] = 130; // = 30mm to end of clipping plate + 100 mm to middle axis of measurement plate
519 m_PointsToTransformGroundTruthProtocol.at(0)[1] = 15;
520 m_PointsToTransformGroundTruthProtocol.at(0)[2] = -7; // = 5mm distance to clipping plate + 2mm to base
521
522 m_PointsToTransformGroundTruthProtocol.at(20)[0] = 130;
523 m_PointsToTransformGroundTruthProtocol.at(20)[1] = 15;
524 m_PointsToTransformGroundTruthProtocol.at(20)[2] = -27; // = 5mm distance to clipping plate + 2mm to base + 20mm depth
525
526 m_PointsToTransformGroundTruthProtocol.at(40)[0] = 130;
527 m_PointsToTransformGroundTruthProtocol.at(40)[1] = 15;
528 m_PointsToTransformGroundTruthProtocol.at(40)[2] = -47; // = 5mm distance to clipping plate + 2mm to base + 40mm depth
529
530 m_PointsToTransformGroundTruthProtocol.at(60)[0] = 130;
531 m_PointsToTransformGroundTruthProtocol.at(60)[1] = 15;
532 m_PointsToTransformGroundTruthProtocol.at(60)[2] = -67; // = 5mm distance to clipping plate + 2mm to base + 60mm depth
533
534 m_PointsToTransformGroundTruthProtocol.at(80)[0] = 130;
535 m_PointsToTransformGroundTruthProtocol.at(80)[1] = 15;
536 m_PointsToTransformGroundTruthProtocol.at(80)[2] = -87; // = 5mm distance to clipping plate + 2mm to base + 80mm depth
537
538 m_PointsToTransformGroundTruthProtocol.at(100)[0] = 130;
539 m_PointsToTransformGroundTruthProtocol.at(100)[1] = 15;
540 m_PointsToTransformGroundTruthProtocol.at(100)[2] = -107; // = 5mm distance to clipping plate + 2mm to base + 100mm depth
541
542 break;
543 // case 2 is equal to fiducial marker configuration C (20mm distance)
544 case 2:
545 m_PointsToTransformGroundTruthProtocol.at(0)[0] = 135; // = 20 + 15mm to end of clipping plate + 100 mm to middle axis of measurement plate
546 m_PointsToTransformGroundTruthProtocol.at(0)[1] = 20;
547 m_PointsToTransformGroundTruthProtocol.at(0)[2] = -9; // = 7mm distance to clipping plate + 2mm to base
548
549 m_PointsToTransformGroundTruthProtocol.at(20)[0] = 135;
550 m_PointsToTransformGroundTruthProtocol.at(20)[1] = 20;
551 m_PointsToTransformGroundTruthProtocol.at(20)[2] = -29; // = 7mm distance to clipping plate + 2mm to base + 20mm depth
552
553 m_PointsToTransformGroundTruthProtocol.at(40)[0] = 135;
554 m_PointsToTransformGroundTruthProtocol.at(40)[1] = 20;
555 m_PointsToTransformGroundTruthProtocol.at(40)[2] = -49; // = 7mm distance to clipping plate + 2mm to base + 40mm depth
556
557 m_PointsToTransformGroundTruthProtocol.at(60)[0] = 135;
558 m_PointsToTransformGroundTruthProtocol.at(60)[1] = 20;
559 m_PointsToTransformGroundTruthProtocol.at(60)[2] = -69; // = 7mm distance to clipping plate + 2mm to base + 60mm depth
560
561 m_PointsToTransformGroundTruthProtocol.at(80)[0] = 135;
562 m_PointsToTransformGroundTruthProtocol.at(80)[1] = 20;
563 m_PointsToTransformGroundTruthProtocol.at(80)[2] = -89; // = 7mm distance to clipping plate + 2mm to base + 80mm depth
564
565 m_PointsToTransformGroundTruthProtocol.at(100)[0] = 135;
566 m_PointsToTransformGroundTruthProtocol.at(100)[1] = 20;
567 m_PointsToTransformGroundTruthProtocol.at(100)[2] = -109; // = 7mm distance to clipping plate + 2mm to base + 100mm depth
568 break;
569 }
570}
571
573{
574 if (m_GroundTruthProtocolTransformedPoints.find(0) == m_GroundTruthProtocolTransformedPoints.end())
575 {
576 mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
577 pointSet->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(0)));
578 m_GroundTruthProtocolTransformedPoints.insert(std::pair<int, mitk::PointSet::Pointer>(0, pointSet));
579 }
580 else
581 {
582 m_GroundTruthProtocolTransformedPoints.at(0)->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(0)));
583 }
584
585 if (m_GroundTruthProtocolTransformedPoints.find(20) == m_GroundTruthProtocolTransformedPoints.end())
586 {
587 mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
588 pointSet->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(20)));
589 m_GroundTruthProtocolTransformedPoints.insert(std::pair<int, mitk::PointSet::Pointer>(20, pointSet));
590 }
591 else
592 {
593 m_GroundTruthProtocolTransformedPoints.at(20)->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(20)));
594 }
595
596 if (m_GroundTruthProtocolTransformedPoints.find(40) == m_GroundTruthProtocolTransformedPoints.end())
597 {
598 mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
599 pointSet->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(40)));
600 m_GroundTruthProtocolTransformedPoints.insert(std::pair<int, mitk::PointSet::Pointer>(40, pointSet));
601 }
602 else
603 {
604 m_GroundTruthProtocolTransformedPoints.at(40)->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(40)));
605 }
606
607 if (m_GroundTruthProtocolTransformedPoints.find(60) == m_GroundTruthProtocolTransformedPoints.end())
608 {
609 mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
610 pointSet->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(60)));
611 m_GroundTruthProtocolTransformedPoints.insert(std::pair<int, mitk::PointSet::Pointer>(60, pointSet));
612 }
613 else
614 {
615 m_GroundTruthProtocolTransformedPoints.at(60)->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(60)));
616 }
617
618 if (m_GroundTruthProtocolTransformedPoints.find(80) == m_GroundTruthProtocolTransformedPoints.end())
619 {
620 mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
621 pointSet->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(80)));
622 m_GroundTruthProtocolTransformedPoints.insert(std::pair<int, mitk::PointSet::Pointer>(80, pointSet));
623 }
624 else
625 {
626 m_GroundTruthProtocolTransformedPoints.at(80)->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(80)));
627 }
628
629 if (m_GroundTruthProtocolTransformedPoints.find(100) == m_GroundTruthProtocolTransformedPoints.end())
630 {
631 mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
632 pointSet->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(100)));
633 m_GroundTruthProtocolTransformedPoints.insert(std::pair<int, mitk::PointSet::Pointer>(100, pointSet));
634 }
635 else
636 {
637 m_GroundTruthProtocolTransformedPoints.at(100)->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(100)));
638 }
639
640}
641
643{
644 if (m_GroundTruthProtocolTransformedPoints.find(0) == m_GroundTruthProtocolTransformedPoints.end() ||
645 m_GroundTruthProtocolTransformedPoints.find(20) == m_GroundTruthProtocolTransformedPoints.end() ||
646 m_GroundTruthProtocolTransformedPoints.find(40) == m_GroundTruthProtocolTransformedPoints.end() ||
647 m_GroundTruthProtocolTransformedPoints.find(60) == m_GroundTruthProtocolTransformedPoints.end() ||
648 m_GroundTruthProtocolTransformedPoints.find(80) == m_GroundTruthProtocolTransformedPoints.end() ||
649 m_GroundTruthProtocolTransformedPoints.find(100) == m_GroundTruthProtocolTransformedPoints.end())
650 {
651 QMessageBox msgBox;
652 msgBox.setText("Cannot add transformed Points to DataStorage because they do not exist.\
653 Stopping evaluation the protocol.");
654 msgBox.exec();
655 return;
656 }
657
658 std::string nameNode0mm = "GroundTruthProt-Depth0mm";
659 std::string nameNode20mm = "GroundTruthProt-Depth20mm";
660 std::string nameNode40mm = "GroundTruthProt-Depth40mm";
661 std::string nameNode60mm = "GroundTruthProt-Depth60mm";
662 std::string nameNode80mm = "GroundTruthProt-Depth80mm";
663 std::string nameNode100mm = "GroundTruthProt-Depth100mm";
664
665 //Add transformed points of depth 0mm to the data storage
666 mitk::DataNode::Pointer node0mm = this->GetDataStorage()->GetNamedNode(nameNode0mm);
667 if (node0mm.IsNull())
668 {
669 node0mm = mitk::DataNode::New();
670 node0mm->SetName(nameNode0mm);
671 node0mm->SetData(m_GroundTruthProtocolTransformedPoints.at(0));
672 this->GetDataStorage()->Add(node0mm);
673 }
674 else
675 {
676 node0mm->SetData(m_GroundTruthProtocolTransformedPoints.at(0));
677 this->GetDataStorage()->Modified();
678 }
679
680 if(ui->protocolEvaluationTypeComboBox->currentText().compare("PLANE") == 0 )
681 {
682 //Add transformed points of depth 20mm to the data storage
683 mitk::DataNode::Pointer node20mm = this->GetDataStorage()->GetNamedNode(nameNode20mm);
684 if (node20mm.IsNull())
685 {
686 node20mm = mitk::DataNode::New();
687 node20mm->SetName(nameNode20mm);
688 node20mm->SetData(m_GroundTruthProtocolTransformedPoints.at(20));
689 this->GetDataStorage()->Add(node20mm);
690 }
691 else
692 {
693 node20mm->SetData(m_GroundTruthProtocolTransformedPoints.at(20));
694 this->GetDataStorage()->Modified();
695 }
696
697 //Add transformed points of depth 40mm to the data storage
698 mitk::DataNode::Pointer node40mm = this->GetDataStorage()->GetNamedNode(nameNode40mm);
699 if (node40mm.IsNull())
700 {
701 node40mm = mitk::DataNode::New();
702 node40mm->SetName(nameNode40mm);
703 node40mm->SetData(m_GroundTruthProtocolTransformedPoints.at(40));
704 this->GetDataStorage()->Add(node40mm);
705 }
706 else
707 {
708 node40mm->SetData(m_GroundTruthProtocolTransformedPoints.at(40));
709 this->GetDataStorage()->Modified();
710 }
711
712 //Add transformed points of depth 60mm to the data storage
713 mitk::DataNode::Pointer node60mm = this->GetDataStorage()->GetNamedNode(nameNode60mm);
714 if (node60mm.IsNull())
715 {
716 node60mm = mitk::DataNode::New();
717 node60mm->SetName(nameNode60mm);
718 node60mm->SetData(m_GroundTruthProtocolTransformedPoints.at(60));
719 this->GetDataStorage()->Add(node60mm);
720 }
721 else
722 {
723 node60mm->SetData(m_GroundTruthProtocolTransformedPoints.at(60));
724 this->GetDataStorage()->Modified();
725 }
726
727 //Add transformed points of depth 80mm to the data storage
728 mitk::DataNode::Pointer node80mm = this->GetDataStorage()->GetNamedNode(nameNode80mm);
729 if (node80mm.IsNull())
730 {
731 node80mm = mitk::DataNode::New();
732 node80mm->SetName(nameNode80mm);
733 node80mm->SetData(m_GroundTruthProtocolTransformedPoints.at(80));
734 this->GetDataStorage()->Add(node80mm);
735 }
736 else
737 {
738 node80mm->SetData(m_GroundTruthProtocolTransformedPoints.at(80));
739 this->GetDataStorage()->Modified();
740 }
741
742 //Add transformed points of depth 100mm to the data storage
743 mitk::DataNode::Pointer node100mm = this->GetDataStorage()->GetNamedNode(nameNode100mm);
744 if (node100mm.IsNull())
745 {
746 node100mm = mitk::DataNode::New();
747 node100mm->SetName(nameNode100mm);
748 node100mm->SetData(m_GroundTruthProtocolTransformedPoints.at(100));
749 this->GetDataStorage()->Add(node100mm);
750 }
751 else
752 {
753 node100mm->SetData(m_GroundTruthProtocolTransformedPoints.at(100));
754 this->GetDataStorage()->Modified();
755 }
756 }
757 //Do a global reinit
758 mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage());
759}
760
762{
763 double meanFRE = 0.0;
764 for (unsigned int counter = 0; counter < m_GroundTruthProtocolFRE.size(); ++counter)
765 {
766 meanFRE += m_GroundTruthProtocolFRE[counter];
767 }
768
769 return meanFRE / m_GroundTruthProtocolFRE.size();
770}
771
773{
774 double variance = 0.0;
775
776 for (unsigned int counter = 0; counter < m_GroundTruthProtocolFRE.size(); ++counter)
777 {
778 variance += ((meanFRE - m_GroundTruthProtocolFRE[counter]) * (meanFRE - m_GroundTruthProtocolFRE[counter]));
779 }
780 variance /= m_GroundTruthProtocolFRE.size(); // calculate the empirical variance (n) and not the sampling variance (n-1)
781
782 return sqrt(variance);
783}
784
786{
787 if (m_GroundTruthProtocolTransformedPoints.find(0) == m_GroundTruthProtocolTransformedPoints.end() ||
788 m_GroundTruthProtocolTransformedPoints.find(20) == m_GroundTruthProtocolTransformedPoints.end() ||
789 m_GroundTruthProtocolTransformedPoints.find(40) == m_GroundTruthProtocolTransformedPoints.end() ||
790 m_GroundTruthProtocolTransformedPoints.find(60) == m_GroundTruthProtocolTransformedPoints.end() ||
791 m_GroundTruthProtocolTransformedPoints.find(80) == m_GroundTruthProtocolTransformedPoints.end() ||
792 m_GroundTruthProtocolTransformedPoints.find(100) == m_GroundTruthProtocolTransformedPoints.end())
793 {
794 QMessageBox msgBox;
795 msgBox.setText("Cannot calculate TRE of Ground-Truth-Protocol because points were not transformed.");
796 msgBox.exec();
797 return;
798 }
799
800 // clear the std::map containing possibly data of earlier TRE calculations
801 m_GroundTruthProtocolTRE.clear();
802 // loop through all existing point sets containing the transformed points
803 for (int counter = 0;
804 m_GroundTruthProtocolTransformedPoints.find(counter) != m_GroundTruthProtocolTransformedPoints.end();
805 counter += 20)
806 {
807 //calculate the middle point of the point set
808 mitk::PointSet::Pointer pointSet = m_GroundTruthProtocolTransformedPoints.at(counter);
809 mitk::Point3D middlePoint;
810 middlePoint[0] = 0.0;
811 middlePoint[1] = 0.0;
812 middlePoint[2] = 0.0;
813
814 for (int position = 0; position < pointSet->GetSize(); ++position)
815 {
816 middlePoint[0] += pointSet->GetPoint(position)[0];
817 middlePoint[1] += pointSet->GetPoint(position)[1];
818 middlePoint[2] += pointSet->GetPoint(position)[2];
819 }
820 middlePoint[0] /= pointSet->GetSize();
821 middlePoint[1] /= pointSet->GetSize();
822 middlePoint[2] /= pointSet->GetSize();
823 MITK_INFO << "Calculated MiddlePoint: " << middlePoint;
824
825 //sum up the euclidean distances between the middle point and each transformed point
826 double meanDistance = 0.0;
827 for (int position = 0; position < pointSet->GetSize(); ++position)
828 {
829 meanDistance += middlePoint.SquaredEuclideanDistanceTo(pointSet->GetPoint(position));
830 MITK_INFO << "SquaredEuclideanDistance: " << middlePoint.SquaredEuclideanDistanceTo(pointSet->GetPoint(position));
831 }
832
833 meanDistance /= pointSet->GetSize(); // this can be interpreted as empirical variance
834 // the root of the empirical variance can be interpreted as the protocols registration TRE
835 m_GroundTruthProtocolTRE.insert(std::pair<int, double>(counter, sqrt(meanDistance)));
836 MITK_INFO << "Ground-Truth-Protocol TRE: " << sqrt(meanDistance);
837 }
838
839}
840
842 ImageType::Pointer binaryImage)
843{
844 BinaryImageToShapeLabelMapFilterType::OutputImageType::Pointer labelMap =
845 m_BinaryImageToShapeLabelMapFilter->GetOutput();
846 double voxelVolume = this->GetVoxelVolume();
847 double fiducialVolume;
848 unsigned int numberOfPixels;
849
850 if (ui->fiducialDiameter3mmRadioButton->isChecked())
851 {
852 fiducialVolume = this->GetFiducialVolume(1.5);
853 numberOfPixels = ceil(fiducialVolume / voxelVolume);
854 }
855 else
856 {
857 fiducialVolume = this->GetFiducialVolume(2.5);
858 numberOfPixels = ceil(fiducialVolume / voxelVolume);
859 }
860
861 MITK_INFO << "Voxel Volume = " << voxelVolume << "; Fiducial Volume = " << fiducialVolume;
862 MITK_INFO << "Number of pixels = " << numberOfPixels;
863
864 labelMap = m_BinaryImageToShapeLabelMapFilter->GetOutput();
865 // The output of this filter is an itk::LabelMap, which contains itk::LabelObject's
866 MITK_INFO << "There are " << labelMap->GetNumberOfLabelObjects() << " objects.";
867
868 // Loop over each region
869 for (int i = labelMap->GetNumberOfLabelObjects() - 1; i >= 0; --i)
870 {
871 // Get the ith region
872 BinaryImageToShapeLabelMapFilterType::OutputImageType::LabelObjectType* labelObject = labelMap->GetNthLabelObject(i);
873 MITK_INFO << "Object " << i << " contains " << labelObject->Size() << " pixel";
874
875 //TODO: Threshold-Wert evtl. experimentell besser abstimmen,
876 // um zu verhindern, dass durch Threshold wahre Fiducial-Kandidaten elimiert werden.
877 if (labelObject->Size() < numberOfPixels * 0.8)
878 {
879 for (unsigned int pixelId = 0; pixelId < labelObject->Size(); pixelId++)
880 {
881 binaryImage->SetPixel(labelObject->GetIndex(pixelId), 0);
882 }
883 labelMap->RemoveLabelObject(labelObject);
884 }
885 }
886}
887
889{
890 if (m_CentroidsOfFiducialCandidates.size() < NUMBER_FIDUCIALS_NEEDED)
891 {
892 return false;
893 }
894
895 for (unsigned int counter = 0; counter < m_CentroidsOfFiducialCandidates.size(); ++counter)
896 {
897 int amountOfAcceptedFiducials = 0;
898 mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(counter));
899 //Loop through all fiducial candidates and calculate the distance between the chosen fiducial
900 // candidate and the other candidates. For each candidate with a right distance between
901 // Configuration A: 7.93mm and 31.0mm (10 mm distance between fiducial centers) or
902 // Configuration B: 11.895mm and 45.0mm (15 mm distance between fiducial centers) or
903 // Configuration C: 15.86mm and 59.0mm (20 mm distance between fiducial centers)
904 //
905 // increase the amountOfAcceptedFiducials.
906 for (unsigned int position = 0; position < m_CentroidsOfFiducialCandidates.size(); ++position)
907 {
908 if (position == counter)
909 {
910 continue;
911 }
912 mitk::Point3D otherCentroid(m_CentroidsOfFiducialCandidates.at(position));
913 double distance = fiducialCentroid.EuclideanDistanceTo(otherCentroid);
914
915 switch (ui->fiducialMarkerConfigurationComboBox->currentIndex())
916 {
917 // case 0 is equal to fiducial marker configuration A (10mm distance)
918 case 0:
919 if (distance > 7.93 && distance < 31.0)
920 {
921 ++amountOfAcceptedFiducials;
922 }
923 break;
924 // case 1 is equal to fiducial marker configuration B (15mm distance)
925 case 1:
926 if (distance > 11.895 && distance < 45.0)
927 {
928 ++amountOfAcceptedFiducials;
929 }
930 break;
931 // case 2 is equal to fiducial marker configuration C (20mm distance)
932 case 2:
933 if (distance > 15.86 && distance < 59.0)
934 {
935 ++amountOfAcceptedFiducials;
936 }
937 break;
938 }
939 }
940 //The amountOfAcceptedFiducials must be at least 7. Otherwise delete the fiducial candidate
941 // from the list of candidates.
942 if (amountOfAcceptedFiducials < NUMBER_FIDUCIALS_NEEDED - 1)
943 {
944 MITK_INFO << "Deleting fiducial candidate at position: " <<
945 m_CentroidsOfFiducialCandidates.at(counter);
946 m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + counter);
947 if (m_CentroidsOfFiducialCandidates.size() < NUMBER_FIDUCIALS_NEEDED )
948 {
949 return false;
950 }
951 counter = -1;
952 }
953 }
954
955 //Classify the rested fiducial candidates by its characteristic Euclidean distances
956 // between the candidates and remove all candidates with a false distance configuration:
958 return true;
959}
960
962{
963 MITK_INFO << "ClassifyFiducialCandidates()";
964 std::vector<int> fiducialCandidatesToBeRemoved;
965 std::vector<std::vector<double>> distanceVectorsFiducials;
966 this->CalculateDistancesBetweenFiducials(distanceVectorsFiducials);
967
968 for (unsigned int counter = 0; counter < distanceVectorsFiducials.size(); ++counter)
969 {
970 int distanceA = 0; // => 10,00mm distance
971 int distanceB = 0; // => 14,14mm distance
972 int distanceC = 0; // => 17,32mm distance
973 int distanceD = 0; // => 22,36mm distance
974 int distanceE = 0; // => 24,49mm distance
975 int distanceF = 0; // => 28,28mm distance
976
977 std::vector<double> &distances = distanceVectorsFiducials.at(counter);
978 for (unsigned int number = 0; number < distances.size(); ++number)
979 {
980 double &distance = distances.at(number);
981 switch (ui->fiducialMarkerConfigurationComboBox->currentIndex())
982 {
983 // case 0 is equal to fiducial marker configuration A (10mm distance)
984 case 0:
985 if (distance > 7.93 && distance <= 12.07)
986 {
987 ++distanceA;
988 }
989 else if (distance > 12.07 && distance <= 15.73)
990 {
991 ++distanceB;
992 }
993 else if (distance > 15.73 && distance <= 19.84)
994 {
995 ++distanceC;
996 }
997 else if (distance > 19.84 && distance <= 23.425)
998 {
999 ++distanceD;
1000 }
1001 else if (distance > 23.425 && distance <= 26.385)
1002 {
1003 ++distanceE;
1004 }
1005 else if (distance > 26.385 && distance <= 31.00)
1006 {
1007 ++distanceF;
1008 }
1009 break;
1010
1011 // case 1 is equal to fiducial marker configuration B (15mm distance)
1012 case 1:
1013 if (distance > 11.895 && distance <= 18.105)
1014 {
1015 ++distanceA;
1016 }
1017 else if (distance > 18.105 && distance <= 23.595)
1018 {
1019 ++distanceB;
1020 }
1021 else if (distance > 23.595 && distance <= 29.76)
1022 {
1023 ++distanceC;
1024 }
1025 else if (distance > 29.76 && distance <= 35.1375)
1026 {
1027 ++distanceD;
1028 if (distance > 33.54)
1029 {
1030 ++distanceE;
1031 }
1032 }
1033 else if (distance > 35.1375 && distance <= 39.5775)
1034 {
1035 ++distanceE;
1036 if (distance < 36.735)
1037 {
1038 ++distanceD;
1039 }
1040 }
1041 else if (distance > 39.5775 && distance <= 45.00)
1042 {
1043 ++distanceF;
1044 }
1045 break;
1046
1047 // case 2 is equal to fiducial marker configuration C (20mm distance)
1048 case 2:
1049 if (distance > 15.86 && distance <= 24.14)
1050 {
1051 ++distanceA;
1052 }
1053 else if (distance > 24.14 && distance <= 31.46)
1054 {
1055 ++distanceB;
1056 }
1057 else if (distance > 31.46 && distance <= 39.68)
1058 {
1059 ++distanceC;
1060 }
1061 else if (distance > 39.68 && distance <= 46.85)
1062 {
1063 ++distanceD;
1064 }
1065 else if (distance > 46.85 && distance <= 52.77)
1066 {
1067 ++distanceE;
1068 }
1069 else if (distance > 52.77 && distance <= 59.00)
1070 {
1071 ++distanceF;
1072 }
1073 break;
1074 }
1075 }// End for-loop distances-vector
1076
1077 //Now, having looped through all distances of one fiducial candidate, check
1078 // if the combination of different distances is known. The >= is due to the
1079 // possible occurrence of other fiducial candidates that have an distance equal to
1080 // one of the distances A - E. However, false fiducial candidates outside
1081 // the fiducial marker does not have the right distance configuration:
1082 if (((distanceA >= 2 && distanceD >= 2 && distanceE >= 2 && distanceF >= 1) ||
1083 (distanceA >= 1 && distanceB >= 2 && distanceC >= 1 && distanceD >= 2 && distanceE >= 1) ||
1084 (distanceB >= 2 && distanceD >= 4 && distanceF >= 1) ||
1085 (distanceA >= 1 && distanceB >= 1 && distanceD >= 3 && distanceE >= 1 && distanceF >= 1)) == false)
1086 {
1087 MITK_INFO << "Detected fiducial candidate with unknown distance configuration.";
1088 fiducialCandidatesToBeRemoved.push_back(counter);
1089 }
1090 }
1091 for (int count = fiducialCandidatesToBeRemoved.size() - 1; count >= 0; --count)
1092 {
1093 MITK_INFO << "Removing fiducial candidate " << fiducialCandidatesToBeRemoved.at(count);
1094 m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin()
1095 + fiducialCandidatesToBeRemoved.at(count));
1096 }
1097}
1098
1100{
1101 MITK_INFO << "GetCentroidsOfLabeledObjects()";
1102 BinaryImageToShapeLabelMapFilterType::OutputImageType::Pointer labelMap =
1103 m_BinaryImageToShapeLabelMapFilter->GetOutput();
1104 for (int i = labelMap->GetNumberOfLabelObjects() - 1; i >= 0; --i)
1105 {
1106 // Get the ith region
1107 BinaryImageToShapeLabelMapFilterType::OutputImageType::LabelObjectType* labelObject = labelMap->GetNthLabelObject(i);
1108 MITK_INFO << "Object " << i << " contains " << labelObject->Size() << " pixel";
1109
1110 mitk::Vector3D centroid;
1111 centroid[0] = labelObject->GetCentroid()[0];
1112 centroid[1] = labelObject->GetCentroid()[1];
1113 centroid[2] = labelObject->GetCentroid()[2];
1114 m_CentroidsOfFiducialCandidates.push_back(centroid);
1115 }
1116 //evtl. for later: itk::LabelMapOverlayImageFilter
1117}
1118
1120{
1121 MITK_INFO << "NumerateFiducialMarks()";
1122 bool successFiducialNo1;
1123 bool successFiducialNo4;
1124 bool successFiducialNo2And3;
1125 bool successFiducialNo5;
1126 bool successFiducialNo8;
1127 bool successFiducialNo6;
1128 bool successFiducialNo7;
1129
1130 std::vector<std::vector<double>> distanceVectorsFiducials;
1131 this->CalculateDistancesBetweenFiducials(distanceVectorsFiducials);
1132 successFiducialNo1 = this->FindFiducialNo1(distanceVectorsFiducials);
1133 successFiducialNo4 = this->FindFiducialNo4(distanceVectorsFiducials);
1134 successFiducialNo2And3 = this->FindFiducialNo2And3();
1135 successFiducialNo5 = this->FindFiducialNo5();
1136 successFiducialNo8 = this->FindFiducialNo8();
1137 successFiducialNo6 = this->FindFiducialNo6();
1138 successFiducialNo7 = this->FindFiducialNo7();
1139
1140 if (!successFiducialNo1 || !successFiducialNo4 || !successFiducialNo2And3 ||
1141 !successFiducialNo5 || !successFiducialNo8 || !successFiducialNo6 || !successFiducialNo7)
1142 {
1143 QMessageBox msgBox;
1144 msgBox.setText("Cannot numerate/localize all fiducials successfully.");
1145 msgBox.exec();
1146 return;
1147 }
1148
1149 if (m_MarkerFloatingImageCoordinateSystemPointSet.IsNull())
1150 {
1151 m_MarkerFloatingImageCoordinateSystemPointSet = mitk::PointSet::New();
1152 }
1153 else if (m_MarkerFloatingImageCoordinateSystemPointSet->GetSize() != 0)
1154 {
1155 m_MarkerFloatingImageCoordinateSystemPointSet->Clear();
1156 }
1157
1158 for (unsigned int counter = 1; counter <= m_FiducialMarkerCentroids.size(); ++counter)
1159 {
1160 m_MarkerFloatingImageCoordinateSystemPointSet->InsertPoint(counter - 1, mitk::Point3D(m_FiducialMarkerCentroids.at(counter)));
1161 }
1162 if( !m_PerformingGroundTruthProtocolEvaluation )
1163 {
1164 mitk::DataNode::Pointer node = mitk::DataNode::New();
1165 node->SetData(m_MarkerFloatingImageCoordinateSystemPointSet);
1166 node->SetName("MarkerFloatingImageCSPointSet");
1167 //node->SetFloatProperty("pointsize", 5.0);
1168 this->GetDataStorage()->Add(node);
1169 }
1170}
1171
1172void QmitkUSNavigationStepCtUsRegistration::CalculateDistancesBetweenFiducials(std::vector<std::vector<double>>& distanceVectorsFiducials)
1173{
1174 std::vector<double> distancesBetweenFiducials;
1175
1176 for (unsigned int i = 0; i < m_CentroidsOfFiducialCandidates.size(); ++i)
1177 {
1178 distancesBetweenFiducials.clear();
1179 mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(i));
1180 for (unsigned int n = 0; n < m_CentroidsOfFiducialCandidates.size(); ++n)
1181 {
1182 mitk::Point3D otherCentroid(m_CentroidsOfFiducialCandidates.at(n));
1183 distancesBetweenFiducials.push_back(fiducialCentroid.EuclideanDistanceTo(otherCentroid));
1184 }
1185 //Sort the distances from low to big numbers
1186 std::sort(distancesBetweenFiducials.begin(), distancesBetweenFiducials.end());
1187 //First entry of the distance vector must be 0, so erase it
1188 if (distancesBetweenFiducials.at(0) == 0.0)
1189 {
1190 distancesBetweenFiducials.erase(distancesBetweenFiducials.begin());
1191 }
1192 //Add the distance vector to the collecting distances vector
1193 distanceVectorsFiducials.push_back(distancesBetweenFiducials);
1194 }
1195
1196 for (unsigned int i = 0; i < distanceVectorsFiducials.size(); ++i)
1197 {
1198 MITK_INFO << "Vector " << i << ":";
1199 for (unsigned int k = 0; k < distanceVectorsFiducials.at(i).size(); ++k)
1200 {
1201 MITK_INFO << distanceVectorsFiducials.at(i).at(k);
1202 }
1203 }
1204}
1205
1206bool QmitkUSNavigationStepCtUsRegistration::FindFiducialNo1(std::vector<std::vector<double>>& distanceVectorsFiducials)
1207{
1208 for (unsigned int i = 0; i < distanceVectorsFiducials.size(); ++i)
1209 {
1210 std::vector<double> &distances = distanceVectorsFiducials.at(i);
1211 if (distances.size() < NUMBER_FIDUCIALS_NEEDED - 1 )
1212 {
1213 MITK_WARN << "Cannot find fiducial 1, there aren't found enough fiducial candidates.";
1214 return false;
1215 }
1216 double characteristicDistanceAWithUpperMargin = this->GetCharacteristicDistanceAWithUpperMargin();
1217
1218 if (distances.at(0) <= characteristicDistanceAWithUpperMargin &&
1219 distances.at(1) <= characteristicDistanceAWithUpperMargin)
1220 {
1221 MITK_INFO << "Found Fiducial 1 (PointSet number " << i << ")";
1222 m_FiducialMarkerCentroids.insert( std::pair<int,mitk::Vector3D>(1, m_CentroidsOfFiducialCandidates.at(i)));
1223 distanceVectorsFiducials.erase(distanceVectorsFiducials.begin() + i);
1224 m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + i);
1225 return true;
1226 }
1227 }
1228 return false;
1229}
1230
1232{
1233 if (m_FiducialMarkerCentroids.find(1) == m_FiducialMarkerCentroids.end() )
1234 {
1235 MITK_WARN << "Cannot find fiducial No 2 and 3. Before must be found fiducial No 1.";
1236 return false;
1237 }
1238
1239 mitk::Point3D fiducialNo1(m_FiducialMarkerCentroids.at(1));
1240 mitk::Vector3D fiducialVectorA;
1241 mitk::Vector3D fiducialVectorB;
1242 mitk::Point3D fiducialPointA;
1243 mitk::Point3D fiducialPointB;
1244 bool foundFiducialA = false;
1245 bool foundFiducialB = false;
1246 mitk::Vector3D vectorFiducial1ToFiducialA;
1247 mitk::Vector3D vectorFiducial1ToFiducialB;
1248
1249 for (unsigned int i = 0; i < m_CentroidsOfFiducialCandidates.size(); ++i)
1250 {
1251 mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(i));
1252 double distance = fiducialNo1.EuclideanDistanceTo(fiducialCentroid);
1253 if (distance <= this->GetCharacteristicDistanceAWithUpperMargin())
1254 {
1255 fiducialVectorA = m_CentroidsOfFiducialCandidates.at(i);
1256 fiducialPointA = fiducialCentroid;
1257 m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + i);
1258 foundFiducialA = true;
1259 break;
1260 }
1261 }
1262
1263 for (unsigned int i = 0; i < m_CentroidsOfFiducialCandidates.size(); ++i)
1264 {
1265 mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(i));
1266 double distance = fiducialNo1.EuclideanDistanceTo(fiducialCentroid);
1267 if (distance <= this->GetCharacteristicDistanceAWithUpperMargin())
1268 {
1269 fiducialVectorB = m_CentroidsOfFiducialCandidates.at(i);
1270 fiducialPointB = fiducialCentroid;
1271 m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + i);
1272 foundFiducialB = true;
1273 break;
1274 }
1275 }
1276
1277 if (!foundFiducialA || !foundFiducialB)
1278 {
1279 MITK_WARN << "Cannot identify fiducial candidates 2 and 3";
1280 return false;
1281 }
1282 else if (m_CentroidsOfFiducialCandidates.size() == 0)
1283 {
1284 MITK_WARN << "Too less fiducials detected. Cannot identify fiducial candidates 2 and 3";
1285 return false;
1286 }
1287
1288 vectorFiducial1ToFiducialA = fiducialVectorA - m_FiducialMarkerCentroids.at(1);
1289 vectorFiducial1ToFiducialB = fiducialVectorB - m_FiducialMarkerCentroids.at(1);
1290
1291 vnl_vector<double> crossProductVnl = vnl_cross_3d(vectorFiducial1ToFiducialA.GetVnlVector(), vectorFiducial1ToFiducialB.GetVnlVector());
1292 mitk::Vector3D crossProduct;
1293 crossProduct.SetVnlVector(crossProductVnl);
1294
1295 mitk::Vector3D vectorFiducial1ToRandomLeftFiducial = m_CentroidsOfFiducialCandidates.at(0) - m_FiducialMarkerCentroids.at(1);
1296
1297 double scalarProduct = (crossProduct * vectorFiducial1ToRandomLeftFiducial) /
1298 (crossProduct.GetNorm() * vectorFiducial1ToRandomLeftFiducial.GetNorm());
1299
1300 double alpha = acos(scalarProduct) * 57.29578; //Transform into degree
1301 MITK_INFO << "Scalar Product = " << alpha;
1302
1303 if (alpha <= 90)
1304 {
1305 m_FiducialMarkerCentroids[3] = fiducialVectorA;
1306 m_FiducialMarkerCentroids[2] = fiducialVectorB;
1307 }
1308 else
1309 {
1310 m_FiducialMarkerCentroids[2] = fiducialVectorA;
1311 m_FiducialMarkerCentroids[3] = fiducialVectorB;
1312 }
1313
1314 MITK_INFO << "Found Fiducial 2, PointSet: " << m_FiducialMarkerCentroids.at(2);
1315 MITK_INFO << "Found Fiducial 3, PointSet: " << m_FiducialMarkerCentroids.at(3);
1316
1317 return true;
1318}
1319
1320bool QmitkUSNavigationStepCtUsRegistration::FindFiducialNo4(std::vector<std::vector<double>>& distanceVectorsFiducials)
1321{
1322 double characteristicDistanceBWithLowerMargin = this->GetCharacteristicDistanceBWithLowerMargin();
1323 double characteristicDistanceBWithUpperMargin = this->GetCharacteristicDistanceBWithUpperMargin();
1324
1325 for (unsigned int i = 0; i < distanceVectorsFiducials.size(); ++i)
1326 {
1327 std::vector<double> &distances = distanceVectorsFiducials.at(i);
1328 if (distances.size() < NUMBER_FIDUCIALS_NEEDED - 1)
1329 {
1330 MITK_WARN << "Cannot find fiducial 4, there aren't found enough fiducial candidates.";
1331 return false;
1332 }
1333
1334 if (distances.at(0) > characteristicDistanceBWithLowerMargin &&
1335 distances.at(0) <= characteristicDistanceBWithUpperMargin &&
1336 distances.at(1) > characteristicDistanceBWithLowerMargin &&
1337 distances.at(1) <= characteristicDistanceBWithUpperMargin)
1338 {
1339 MITK_INFO << "Found Fiducial 4 (PointSet number " << i << ")";
1340 m_FiducialMarkerCentroids.insert(std::pair<int, mitk::Vector3D>(4, m_CentroidsOfFiducialCandidates.at(i)));
1341 distanceVectorsFiducials.erase(distanceVectorsFiducials.begin() + i);
1342 m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + i);
1343 return true;
1344 }
1345 }
1346 return false;
1347}
1348
1350{
1351 if (m_FiducialMarkerCentroids.find(2) == m_FiducialMarkerCentroids.end())
1352 {
1353 MITK_WARN << "To find fiducial No 5, fiducial No 2 has to be found before.";
1354 return false;
1355 }
1356
1357 double characteristicDistanceBWithUpperMargin = this->GetCharacteristicDistanceBWithUpperMargin();
1358
1359 mitk::Point3D fiducialNo2(m_FiducialMarkerCentroids.at(2));
1360
1361 for (unsigned int counter = 0; counter < m_CentroidsOfFiducialCandidates.size(); ++counter)
1362 {
1363 mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(counter));
1364 double distance = fiducialNo2.EuclideanDistanceTo(fiducialCentroid);
1365 if (distance <= characteristicDistanceBWithUpperMargin)
1366 {
1367 m_FiducialMarkerCentroids[5] = m_CentroidsOfFiducialCandidates.at(counter);
1368 m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + counter);
1369 MITK_INFO << "Found Fiducial No 5, PointSet: " << m_FiducialMarkerCentroids[5];
1370 return true;
1371 }
1372 }
1373
1374 MITK_WARN << "Cannot find fiducial No 5.";
1375 return false;
1376}
1377
1379{
1380 if (m_FiducialMarkerCentroids.find(5) == m_FiducialMarkerCentroids.end())
1381 {
1382 MITK_WARN << "To find fiducial No 6, fiducial No 5 has to be found before.";
1383 return false;
1384 }
1385
1386 double characteristicDistanceAWithUpperMargin = this->GetCharacteristicDistanceAWithUpperMargin();
1387
1388 mitk::Point3D fiducialNo5(m_FiducialMarkerCentroids.at(5));
1389
1390 for (unsigned int counter = 0; counter < m_CentroidsOfFiducialCandidates.size(); ++counter)
1391 {
1392 mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(counter));
1393 double distance = fiducialNo5.EuclideanDistanceTo(fiducialCentroid);
1394 if (distance <= characteristicDistanceAWithUpperMargin)
1395 {
1396 m_FiducialMarkerCentroids[6] = m_CentroidsOfFiducialCandidates.at(counter);
1397 m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + counter);
1398 MITK_INFO << "Found Fiducial No 6, PointSet: " << m_FiducialMarkerCentroids[6];
1399 return true;
1400 }
1401 }
1402
1403 MITK_WARN << "Cannot find fiducial No 6.";
1404 return false;
1405}
1406
1408{
1409 if (m_FiducialMarkerCentroids.find(8) == m_FiducialMarkerCentroids.end())
1410 {
1411 MITK_WARN << "To find fiducial No 7, fiducial No 8 has to be found before.";
1412 return false;
1413 }
1414
1415 double characteristicDistanceAWithUpperMargin = this->GetCharacteristicDistanceAWithUpperMargin();
1416
1417 mitk::Point3D fiducialNo8(m_FiducialMarkerCentroids.at(8));
1418
1419 for (unsigned int counter = 0; counter < m_CentroidsOfFiducialCandidates.size(); ++counter)
1420 {
1421 mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(counter));
1422 double distance = fiducialNo8.EuclideanDistanceTo(fiducialCentroid);
1423 if (distance <= characteristicDistanceAWithUpperMargin)
1424 {
1425 m_FiducialMarkerCentroids[7] = m_CentroidsOfFiducialCandidates.at(counter);
1426 m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + counter);
1427 MITK_INFO << "Found Fiducial No 7, PointSet: " << m_FiducialMarkerCentroids[7];
1428 return true;
1429 }
1430 }
1431
1432 MITK_WARN << "Cannot find fiducial No 7.";
1433 return false;
1434}
1435
1437{
1438 if (m_FiducialMarkerCentroids.find(3) == m_FiducialMarkerCentroids.end())
1439 {
1440 MITK_WARN << "To find fiducial No 8, fiducial No 3 has to be found before.";
1441 return false;
1442 }
1443
1444 double characteristicDistanceBWithUpperMargin = this->GetCharacteristicDistanceBWithUpperMargin();
1445
1446 mitk::Point3D fiducialNo3(m_FiducialMarkerCentroids.at(3));
1447
1448 for (unsigned int counter = 0; counter < m_CentroidsOfFiducialCandidates.size(); ++counter)
1449 {
1450 mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(counter));
1451 double distance = fiducialNo3.EuclideanDistanceTo(fiducialCentroid);
1452 if (distance <= characteristicDistanceBWithUpperMargin)
1453 {
1454 m_FiducialMarkerCentroids[8] = m_CentroidsOfFiducialCandidates.at(counter);
1455 m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + counter);
1456 MITK_INFO << "Found Fiducial No 8, PointSet: " << m_FiducialMarkerCentroids[8];
1457 return true;
1458 }
1459 }
1460
1461 MITK_WARN << "Cannot find fiducial No 8.";
1462 return false;
1463}
1464
1466{
1467 m_IsAPointSetPredicate = mitk::TNodePredicateDataType<mitk::PointSet>::New();
1468 mitk::TNodePredicateDataType<mitk::Image>::Pointer isImage = mitk::TNodePredicateDataType<mitk::Image>::New();
1469
1470 auto isSegmentation = mitk::NodePredicateDataType::New("Segment");
1471 m_IsASurfacePredicate = mitk::NodePredicateDataType::New("Surface");
1472
1473 mitk::NodePredicateOr::Pointer validImages = mitk::NodePredicateOr::New();
1474 validImages->AddPredicate(mitk::NodePredicateAnd::New(isImage, mitk::NodePredicateNot::New(isSegmentation)));
1475
1476 mitk::NodePredicateNot::Pointer isNotAHelperObject = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true)));
1477
1478 m_IsOfTypeImagePredicate = mitk::NodePredicateAnd::New(validImages, isNotAHelperObject);
1479
1480 mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
1481 mitk::NodePredicateNot::Pointer isNotBinaryPredicate = mitk::NodePredicateNot::New(isBinaryPredicate);
1482
1483 mitk::NodePredicateAnd::Pointer isABinaryImagePredicate = mitk::NodePredicateAnd::New(m_IsOfTypeImagePredicate, isBinaryPredicate);
1484 mitk::NodePredicateAnd::Pointer isNotABinaryImagePredicate = mitk::NodePredicateAnd::New(m_IsOfTypeImagePredicate, isNotBinaryPredicate);
1485
1486 m_IsASegmentationImagePredicate = mitk::NodePredicateOr::New(isABinaryImagePredicate, mitk::TNodePredicateDataType<mitk::LabelSetImage>::New());
1487 m_IsAPatientImagePredicate = mitk::NodePredicateAnd::New(isNotABinaryImagePredicate, mitk::NodePredicateNot::New(mitk::TNodePredicateDataType<mitk::LabelSetImage>::New()));
1488}
1489
1491{
1492 ui->setupUi(parent);
1493 ui->floatingImageComboBox->SetPredicate(m_IsAPatientImagePredicate);
1494 ui->ctImagesToChooseComboBox->SetPredicate(m_IsAPatientImagePredicate);
1495 ui->segmentationComboBox->SetPredicate(m_IsASegmentationImagePredicate);
1496 ui->selectedSurfaceComboBox->SetPredicate(m_IsASurfacePredicate);
1497 ui->pointSetComboBox->SetPredicate(m_IsAPointSetPredicate);
1498
1499 // create signal/slot connections
1500 connect(ui->floatingImageComboBox, SIGNAL(OnSelectionChanged(const mitk::DataNode*)),
1501 this, SLOT(OnFloatingImageComboBoxSelectionChanged(const mitk::DataNode*)));
1502 connect(ui->doRegistrationMarkerToImagePushButton, SIGNAL(clicked()),
1503 this, SLOT(OnRegisterMarkerToFloatingImageCS()));
1504 connect(ui->localizeFiducialMarkerPushButton, SIGNAL(clicked()),
1505 this, SLOT(OnLocalizeFiducials()));
1506 connect(ui->visualizeCTtoUSregistrationPushButton, SIGNAL(clicked()),
1507 this, SLOT(OnVisualizeCTtoUSregistration()));
1508 connect(ui->freezeUnfreezePushButton, SIGNAL(clicked()),
1509 this, SLOT(OnFreeze()));
1510 connect(ui->addCtImagePushButton, SIGNAL(clicked()),
1511 this, SLOT(OnAddCtImageClicked()));
1512 connect(ui->removeCtImagePushButton, SIGNAL(clicked()),
1513 this, SLOT(OnRemoveCtImageClicked()));
1514 connect(ui->evaluateProtocolPushButton, SIGNAL(clicked()),
1516 connect(ui->actualizeSegmentationSurfacePSetDataPushButton, SIGNAL(clicked()),
1518 connect(ui->calculateTREPushButton, SIGNAL(clicked()),
1519 this, SLOT(OnGetCursorPosition()));
1520 connect(ui->calculateCenterPushButton, SIGNAL(clicked()),
1521 this, SLOT(OnCalculateCenter()));
1522}
1523
1525{
1526 MITK_INFO << "OnFloatingImageComboBoxSelectionChanged()";
1527
1528 if (m_FloatingImage.IsNotNull())
1529 {
1530 //TODO: Define, what will happen if the imageCT is not null...
1531 }
1532
1533 if (node == nullptr)
1534 {
1536 m_FloatingImage = nullptr;
1537 return;
1538 }
1539
1540 mitk::DataNode* selectedFloatingImage = ui->floatingImageComboBox->GetSelectedNode();
1541 if (selectedFloatingImage == nullptr)
1542 {
1544 m_FloatingImage = nullptr;
1545 return;
1546 }
1547
1548 mitk::Image::Pointer floatingImage = dynamic_cast<mitk::Image*>(selectedFloatingImage->GetData());
1549 if (floatingImage.IsNull())
1550 {
1551 MITK_WARN << "Failed to cast selected segmentation node to mitk::Image*";
1553 m_FloatingImage = nullptr;
1554 return;
1555 }
1556
1557 m_FloatingImage = floatingImage;
1558 this->SetFloatingImageGeometryInformation(floatingImage.GetPointer());
1559}
1560
1562{
1564
1565 //Check for initialization
1566 if( m_MarkerModelCoordinateSystemPointSet.IsNull() ||
1567 m_MarkerFloatingImageCoordinateSystemPointSet.IsNull() )
1568 {
1569 MITK_WARN << "Fiducial Landmarks are not initialized yet, cannot register";
1570 return;
1571 }
1572
1573 //Retrieve fiducials
1574 if (m_MarkerFloatingImageCoordinateSystemPointSet->GetSize() != m_MarkerModelCoordinateSystemPointSet->GetSize())
1575 {
1576 MITK_WARN << "Not the same number of fiducials, cannot register";
1577 return;
1578 }
1579 else if (m_MarkerFloatingImageCoordinateSystemPointSet->GetSize() < 3)
1580 {
1581 MITK_WARN << "Need at least 3 fiducials, cannot register";
1582 return;
1583 }
1584
1585 //############### conversion to vtk data types (we will use the vtk landmark based transform) ##########################
1586 //convert point sets to vtk poly data
1589 for (int i = 0; i<m_MarkerModelCoordinateSystemPointSet->GetSize(); i++)
1590 {
1591 double point[3] = { m_MarkerModelCoordinateSystemPointSet->GetPoint(i)[0],
1592 m_MarkerModelCoordinateSystemPointSet->GetPoint(i)[1],
1593 m_MarkerModelCoordinateSystemPointSet->GetPoint(i)[2] };
1594 sourcePoints->InsertNextPoint(point);
1595
1596 double point_targets[3] = { m_MarkerFloatingImageCoordinateSystemPointSet->GetPoint(i)[0],
1597 m_MarkerFloatingImageCoordinateSystemPointSet->GetPoint(i)[1],
1598 m_MarkerFloatingImageCoordinateSystemPointSet->GetPoint(i)[2] };
1599 targetPoints->InsertNextPoint(point_targets);
1600 }
1601
1602 //########################### here, the actual transform is computed ##########################
1603 //compute transform
1605 transform->SetSourceLandmarks(sourcePoints);
1606 transform->SetTargetLandmarks(targetPoints);
1607 transform->SetModeToRigidBody();
1608 transform->Modified();
1609 transform->Update();
1610 //compute FRE of transform
1611
1612 double FRE = mitk::StaticIGTHelperFunctions::ComputeFRE(m_MarkerModelCoordinateSystemPointSet, m_MarkerFloatingImageCoordinateSystemPointSet, transform);
1613 MITK_INFO << "FRE: " << FRE << " mm";
1614 if (m_PerformingGroundTruthProtocolEvaluation)
1615 {
1616 m_GroundTruthProtocolFRE.push_back(FRE);
1617 }
1618 //#############################################################################################
1619
1620 //############### conversion back to itk/mitk data types ##########################
1621 //convert from vtk to itk data types
1622 itk::Matrix<float, 3, 3> rotationFloat = itk::Matrix<float, 3, 3>();
1623 itk::Vector<float, 3> translationFloat = itk::Vector<float, 3>();
1624 itk::Matrix<double, 3, 3> rotationDouble = itk::Matrix<double, 3, 3>();
1625 itk::Vector<double, 3> translationDouble = itk::Vector<double, 3>();
1626
1627 vtkSmartPointer<vtkMatrix4x4> m = transform->GetMatrix();
1628 for (int k = 0; k<3; k++) for (int l = 0; l<3; l++)
1629 {
1630 rotationFloat[k][l] = m->GetElement(k, l);
1631 rotationDouble[k][l] = m->GetElement(k, l);
1632
1633 }
1634 for (int k = 0; k<3; k++)
1635 {
1636 translationFloat[k] = m->GetElement(k, 3);
1637 translationDouble[k] = m->GetElement(k, 3);
1638 }
1639 //create mitk affine transform 3D and save it to the class member
1640 m_TransformMarkerCSToFloatingImageCS = mitk::AffineTransform3D::New();
1641 m_TransformMarkerCSToFloatingImageCS->SetMatrix(rotationDouble);
1642 m_TransformMarkerCSToFloatingImageCS->SetOffset(translationDouble);
1643 MITK_INFO << m_TransformMarkerCSToFloatingImageCS;
1644 //################################################################
1645
1646 //############### object is transformed ##########################
1647 //transform surface/image
1648 //only move image if we have one. Sometimes, this widget is used just to register point sets without images.
1649
1650 /*if (m_ImageNode.IsNotNull())
1651 {
1652 //first we have to store the original ct image transform to compose it with the new transform later
1653 mitk::AffineTransform3D::Pointer imageTransform = m_ImageNode->GetData()->GetGeometry()->GetIndexToWorldTransform();
1654 imageTransform->Compose(mitkTransform);
1655 mitk::AffineTransform3D::Pointer newImageTransform = mitk::AffineTransform3D::New(); //create new image transform... setting the composed directly leads to an error
1656 itk::Matrix<mitk::ScalarType, 3, 3> rotationFloatNew = imageTransform->GetMatrix();
1657 itk::Vector<mitk::ScalarType, 3> translationFloatNew = imageTransform->GetOffset();
1658 newImageTransform->SetMatrix(rotationFloatNew);
1659 newImageTransform->SetOffset(translationFloatNew);
1660 m_ImageNode->GetData()->GetGeometry()->SetIndexToWorldTransform(newImageTransform);
1661 }*/
1662
1663 //If this option is set, each point will be transformed and the actual coordinates of the points change.
1664
1665 if( !m_PerformingGroundTruthProtocolEvaluation )
1666 {
1667 mitk::PointSet* pointSet_orig = m_MarkerModelCoordinateSystemPointSet;
1668 mitk::PointSet::Pointer pointSet_moved = mitk::PointSet::New();
1669
1670 for (int i = 0; i < pointSet_orig->GetSize(); i++)
1671 {
1672 pointSet_moved->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(pointSet_orig->GetPoint(i)));
1673 }
1674
1675 pointSet_orig->Clear();
1676 for (int i = 0; i < pointSet_moved->GetSize(); i++)
1677 pointSet_orig->InsertPoint(pointSet_moved->GetPoint(i));
1678
1679 //Do a global reinit
1680 mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage());
1681 }
1682
1683}
1684
1686{
1687 m_FiducialMarkerCentroids.clear();
1688 m_CentroidsOfFiducialCandidates.clear();
1689 if (m_MarkerFloatingImageCoordinateSystemPointSet.IsNotNull())
1690 {
1691 m_MarkerFloatingImageCoordinateSystemPointSet->Clear();
1692 }
1693
1694 if (!this->FilterFloatingImage())
1695 {
1696 QMessageBox msgBox;
1697 msgBox.setText("Cannot perform filtering of the image. The floating image = nullptr.");
1698 msgBox.exec();
1699 return;
1700 }
1701 mitk::AffineTransform3D::Pointer transform = m_FloatingImage->GetGeometry()->GetIndexToWorldTransform();
1702 MITK_WARN << "IndexToWorldTransform_CTimage = " << transform;
1703
1705
1707 m_CentroidsOfFiducialCandidates.size() != NUMBER_FIDUCIALS_NEEDED)
1708 {
1709 QMessageBox msgBox;
1710 QString text = QString("Have found %1 instead of 8 fiducial candidates.\
1711 Cannot perform fiducial localization procedure.").arg(m_CentroidsOfFiducialCandidates.size());
1712 msgBox.setText(text);
1713 msgBox.exec();
1714 return;
1715 }
1716
1717 //Before calling NumerateFiducialMarks it must be sure,
1718 // that there rested only 8 fiducial candidates.
1719 this->NumerateFiducialMarks();
1720}
1721
1723{
1725
1726 mitk::DataNode* segmentationNode = ui->segmentationComboBox->GetSelectedNode();
1727 if (segmentationNode == nullptr)
1728 {
1729 QMessageBox msgBox;
1730 msgBox.setText("Cannot visualize CT-to-US registration. There is no segmentation selected.");
1731 msgBox.exec();
1732 return;
1733 }
1734 mitk::AffineTransform3D::Pointer transform = segmentationNode->GetData()->GetGeometry()->GetIndexToWorldTransform();
1735 MITK_WARN << "IndexToWorldTransform_segmentation = " << transform;
1736
1737 mitk::DataNode* surfaceNode = ui->selectedSurfaceComboBox->GetSelectedNode();
1738 if (surfaceNode == nullptr)
1739 {
1740 QMessageBox msgBox;
1741 msgBox.setText("Cannot visualize CT-to-US registration. There is no surface selected.");
1742 msgBox.exec();
1743 return;
1744 }
1745
1746 mitk::DataNode* pointSetNode = ui->pointSetComboBox->GetSelectedNode();
1747 if (pointSetNode == nullptr)
1748 {
1749 QMessageBox msgBox;
1750 msgBox.setText("Cannot visualize CT-to-US registration. There is no pointSet selected.");
1751 msgBox.exec();
1752 return;
1753 }
1754
1755 if (this->GetCombinedModality(false).IsNull())
1756 {
1757 QMessageBox msgBox;
1758 msgBox.setText("CombinedModality not yet set.\nPlease try again and click on the button.");
1759 msgBox.exec();
1760 return;
1761 }
1762
1763 if (m_FloatingImageToUltrasoundRegistrationFilter.IsNull())
1764 {
1765 QMessageBox msgBox;
1766 msgBox.setText("Cannot visualize CT-to-US registration.\
1767 The FloatingImageToUltrasoundRegistrationFilter is not initialized.");
1768 msgBox.exec();
1769 return;
1770 }
1771 //Set the transformation from marker-CS to the sensor-CS accordingly to the chosen user-option
1772 m_FloatingImageToUltrasoundRegistrationFilter
1773 ->InitializeTransformationMarkerCSToSensorCS(ui->useNdiTrackerCheckBox->isChecked());
1774 m_FloatingImageToUltrasoundRegistrationFilter->SetPointSet(pointSetNode);
1775 m_FloatingImageToUltrasoundRegistrationFilter->SetSegmentation(segmentationNode, m_FloatingImage);
1776 m_FloatingImageToUltrasoundRegistrationFilter->SetSurface(surfaceNode);
1777 m_FloatingImageToUltrasoundRegistrationFilter
1778 ->SetTransformMarkerCSToFloatingImageCS(m_TransformMarkerCSToFloatingImageCS);
1779 m_FloatingImageToUltrasoundRegistrationFilter
1780 ->SetTransformUSimageCSToTrackingCS(this->GetCombinedModality()->GetCalibration());
1781 m_FloatingImageToUltrasoundRegistrationFilter
1782 ->ConnectTo(this->GetCombinedModality()->GetNavigationDataSource());
1783}
1784
1786{
1787 if (this->GetCombinedModality(false).IsNull())
1788 {
1789 return;
1790 }
1791
1792 if (!m_FreezeCombinedModality)
1793 {
1794 m_FreezeCombinedModality = true;
1795 ui->freezeUnfreezePushButton->setText("Unfreeze");
1796 this->GetCombinedModality()->SetIsFreezed(true);
1797 }
1798 else
1799 {
1800 m_FreezeCombinedModality = false;
1801 ui->freezeUnfreezePushButton->setText("Freeze");
1802 this->GetCombinedModality()->SetIsFreezed(false);
1803 }
1804}
1805
1807{
1808 mitk::DataNode* segmentationNode = ui->segmentationComboBox->GetSelectedNode();
1809 if (segmentationNode == nullptr)
1810 {
1811 QMessageBox msgBox;
1812 msgBox.setText("Cannot actualize segmentation + surface + pointset data. There is no segmentation selected.");
1813 msgBox.exec();
1814 return;
1815 }
1816
1817 mitk::DataNode* surfaceNode = ui->selectedSurfaceComboBox->GetSelectedNode();
1818 if (surfaceNode == nullptr)
1819 {
1820 QMessageBox msgBox;
1821 msgBox.setText("Cannot actualize segmentation + surface + pointset data. There is no surface selected.");
1822 msgBox.exec();
1823 return;
1824 }
1825
1826 mitk::DataNode* pointSetNode = ui->pointSetComboBox->GetSelectedNode();
1827 if (pointSetNode == nullptr)
1828 {
1829 QMessageBox msgBox;
1830 msgBox.setText("Cannot actualize segmentation + surface + pointset data. There is no pointSet selected.");
1831 msgBox.exec();
1832 return;
1833 }
1834
1835 m_FloatingImageToUltrasoundRegistrationFilter->SetPointSet(pointSetNode);
1836 m_FloatingImageToUltrasoundRegistrationFilter->SetSegmentation(segmentationNode, m_FloatingImage);
1837 m_FloatingImageToUltrasoundRegistrationFilter->SetSurface(surfaceNode);
1838}
1839
1844
1845void QmitkUSNavigationStepCtUsRegistration::OnCalculateTRE(mitk::Point3D centroidOfTargetInUSImage)
1846{
1847 mitk::DataNode::Pointer pointSetNode = ui->pointSetComboBox->GetSelectedNode();
1848 if (pointSetNode.IsNull())
1849 {
1850 QMessageBox msgBox;
1851 msgBox.setText("Cannot calculate TRE. The pointSetComboBox node returned a nullptr.");
1852 msgBox.exec();
1853 return;
1854 }
1855
1856 mitk::PointSet::Pointer pointSet = dynamic_cast<mitk::PointSet*>(pointSetNode->GetData());
1857 if (pointSet.IsNull())
1858 {
1859 ui->distanceTREValue->setText(QString("Unknown"));
1860 return;
1861 }
1862 double distance = pointSet->GetPoint(0).EuclideanDistanceTo(centroidOfTargetInUSImage);
1863 ui->distanceTREValue->setText(QString("%1").arg(distance));
1864}
1865
1867{
1868 mitk::DataNode::Pointer node = ui->segmentationComboBox->GetSelectedNode();
1869 if (node.IsNull())
1870 {
1871 QMessageBox msgBox;
1872 msgBox.setText("Cannot calculate the centroid of the segmentation."\
1873 "The segmentationComboBox node returned a nullptr.");
1874 msgBox.exec();
1875 return;
1876 }
1877
1878 mitk::LabelSetImage::Pointer image = dynamic_cast<mitk::LabelSetImage*>(node->GetData());
1879 if (image.IsNull())
1880 {
1881 MITK_WARN << "Cannot CalculateCenter - the segmentation cannot be converted to mitk::Image";
1882 return;
1883 }
1884
1885 ImageType::Pointer itkImage = ImageType::New();
1886 mitk::CastToItkImage(image, itkImage);
1887
1888 //Initialize binary image to shape label map filter
1889 BinaryImageToShapeLabelMapFilterType::Pointer shapeLabelMapFilter = BinaryImageToShapeLabelMapFilterType::New();
1890 shapeLabelMapFilter->SetInputForegroundValue(1);
1891
1892 shapeLabelMapFilter->SetInput(itkImage);
1893 shapeLabelMapFilter->Update();
1894
1895 BinaryImageToShapeLabelMapFilterType::OutputImageType::Pointer labelMap =
1896 shapeLabelMapFilter->GetOutput();
1897 for (int i = labelMap->GetNumberOfLabelObjects() - 1; i >= 0; --i)
1898 {
1899 // Get the ith region
1900 BinaryImageToShapeLabelMapFilterType::OutputImageType::LabelObjectType* labelObject = labelMap->GetNthLabelObject(i);
1901
1902 mitk::Vector3D centroid;
1903 centroid[0] = labelObject->GetCentroid()[0];
1904 centroid[1] = labelObject->GetCentroid()[1];
1905 centroid[2] = labelObject->GetCentroid()[2];
1906 MITK_INFO << "Centroid of segmentation = " << centroid;
1907 }
1908}
1909
1911{
1912 mitk::DataNode* selectedCtImage = ui->ctImagesToChooseComboBox->GetSelectedNode();
1913 if (selectedCtImage == nullptr)
1914 {
1915 return;
1916 }
1917
1918 mitk::Image::Pointer ctImage = dynamic_cast<mitk::Image*>(selectedCtImage->GetData());
1919 if (ctImage.IsNull())
1920 {
1921 MITK_WARN << "Failed to cast selected segmentation node to mitk::Image*";
1922 return;
1923 }
1924 QString name = QString::fromStdString(selectedCtImage->GetName());
1925
1926 for( int counter = 0; counter < ui->chosenCtImagesListWidget->count(); ++counter)
1927 {
1928 MITK_INFO << ui->chosenCtImagesListWidget->item(counter)->text() << " - " << counter;
1929 MITK_INFO << m_ImagesGroundTruthProtocol.at(counter).GetPointer();
1930 if (ui->chosenCtImagesListWidget->item(counter)->text().compare(name) == 0)
1931 {
1932 MITK_INFO << "CT image already exist in list of chosen CT images. Do not add the image.";
1933 return;
1934 }
1935 }
1936
1937 ui->chosenCtImagesListWidget->addItem(name);
1938 m_ImagesGroundTruthProtocol.push_back(ctImage);
1939}
1940
1942{
1943 int position = ui->chosenCtImagesListWidget->currentRow();
1944 if (ui->chosenCtImagesListWidget->count() == 0 || position < 0)
1945 {
1946 return;
1947 }
1948
1949 m_ImagesGroundTruthProtocol.erase(m_ImagesGroundTruthProtocol.begin() + position);
1950 QListWidgetItem *item = ui->chosenCtImagesListWidget->currentItem();
1951 ui->chosenCtImagesListWidget->removeItemWidget(item);
1952 delete item;
1953}
1954
1956{
1957 m_GroundTruthProtocolFRE.clear();
1958 if (m_ImagesGroundTruthProtocol.size() != 6)
1959 {
1960 QMessageBox msgBox;
1961 msgBox.setText("For evaluating the Ground-Truth-Fiducial-Localization-Protocol there must be loaded 6 different CT images.");
1962 msgBox.exec();
1963 return;
1964 }
1965
1966 m_PerformingGroundTruthProtocolEvaluation = true;
1968 m_GroundTruthProtocolTransformedPoints.clear();
1969
1970 for (unsigned int cycleNo = 0; cycleNo < m_ImagesGroundTruthProtocol.size(); ++cycleNo)
1971 {
1972 m_FloatingImage = m_ImagesGroundTruthProtocol.at(cycleNo);
1973 this->SetFloatingImageGeometryInformation(m_FloatingImage.GetPointer());
1974
1975 this->OnLocalizeFiducials();
1978 }
1980 double meanFRE = this->CalculateMeanFRE();
1981 double sdOfFRE = this->CalculateStandardDeviationOfFRE(meanFRE);
1983
1984 ui->meanFREValue->setText(QString("%1").arg(meanFRE));
1985 ui->sdFREValue->setText(QString("%1").arg(sdOfFRE));
1986 if (ui->protocolEvaluationTypeComboBox->currentText().compare("ANGLE") == 0)
1987 {
1988 if (m_GroundTruthProtocolTRE.find(0) != m_GroundTruthProtocolTRE.end())
1989 {
1990 ui->TREValue->setText(QString("%1").arg(m_GroundTruthProtocolTRE.at(0)));
1991 }
1992 }
1993 else if (ui->protocolEvaluationTypeComboBox->currentText().compare("PLANE") == 0)
1994 {
1995 if (m_GroundTruthProtocolTRE.find(0) != m_GroundTruthProtocolTRE.end() &&
1996 m_GroundTruthProtocolTRE.find(20) != m_GroundTruthProtocolTRE.end() &&
1997 m_GroundTruthProtocolTRE.find(40) != m_GroundTruthProtocolTRE.end() &&
1998 m_GroundTruthProtocolTRE.find(60) != m_GroundTruthProtocolTRE.end() &&
1999 m_GroundTruthProtocolTRE.find(80) != m_GroundTruthProtocolTRE.end() &&
2000 m_GroundTruthProtocolTRE.find(100) != m_GroundTruthProtocolTRE.end())
2001 {
2002 ui->TREValue->setText(QString("Depth 0mm: %1\nDepth 20mm: %2\nDepth 40mm: %3\
2003 \nDepth 60mm: %4\nDepth 80mm: %5\nDepth 100mm: %6")
2004 .arg(m_GroundTruthProtocolTRE.at(0))
2005 .arg(m_GroundTruthProtocolTRE.at(20))
2006 .arg(m_GroundTruthProtocolTRE.at(40))
2007 .arg(m_GroundTruthProtocolTRE.at(60))
2008 .arg(m_GroundTruthProtocolTRE.at(80))
2009 .arg(m_GroundTruthProtocolTRE.at(100)));
2010 }
2011 }
2012
2013 m_PerformingGroundTruthProtocolEvaluation = false;
2014}
Abstract base class for navigation step widgets.
itk::SmartPointer< mitk::DataStorage > GetDataStorage(bool throwNull=true)
Returns the data storage set for the navigation step.
itk::SmartPointer< mitk::AbstractUltrasoundTrackerDevice > GetCombinedModality(bool throwNull=true)
Returns the combined modality set for the navigation step.
std::vector< itk::SmartPointer< mitk::NavigationDataToNavigationDataFilter > > FilterVector
Navigation step for marking risk structures. The user can add risk structures by interacting with the...
void OnCalculateTRE(mitk::Point3D centroidOfTargetInUSImage)
void OnSetCombinedModality() override
Called every time SetCombinedModality() was called. This method may be implemented by a concrete subc...
bool FindFiducialNo4(std::vector< std::vector< double > > &distanceVectorsFiducials)
void EliminateTooSmallLabeledObjects(ImageType::Pointer binaryImage)
bool OnStartStep() override
Initialization of the data storage nodes.
void CalculateDistancesBetweenFiducials(std::vector< std::vector< double > > &distanceVectorsFiducials)
void OnFloatingImageComboBoxSelectionChanged(const mitk::DataNode *node)
QString GetTitle() override
Getter for the title of the navigation step. This title should be human readable and can be used to d...
bool FindFiducialNo1(std::vector< std::vector< double > > &distanceVectorsFiducials)
void OnSettingsChanged(const itk::SmartPointer< mitk::DataNode > settingsNode) override
bool OnFinishStep() override
There is nothing to be done.
bool OnActivateStep() override
Selects input for the node displacement filter and emits "ReadyForNextStep" signal....
bool OnDeactivateStep() override
Called when the navigation step gets deactivated (-> state started). This method may be implemented b...
bool OnStopStep() override
Resets widget and filter and removes nodes from the data storage.
void OnUpdate() override
Updates the tracking validity status and the combined modality.
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...