CustusX  22.04-rc5
An IGT application
cxManualImage2ImageRegistrationWidget.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
13 #include "cxRegistrationService.h"
14 #include "cxData.h"
15 #include "cxImage.h"
18 #include "cxPatientModelService.h"
20 #include "cxLandmark.h"
21 
22 #include "vtkMath.h"
23 
24 namespace cx
25 {
26 
27 
29  ManualImageRegistrationWidget(services, parent, objectName, "Manual Image to Image Registration")
30 {
31  StringPropertyBasePtr fixedImage(new StringPropertyRegistrationFixedImage(services->registration(), services->patient()));
32  StringPropertyBasePtr movingImage(new StringPropertyRegistrationMovingImage(services->registration(), services->patient()));
33 
34  LabeledComboBoxWidget* fixed = new LabeledComboBoxWidget(this, fixedImage);
35  LabeledComboBoxWidget* moving = new LabeledComboBoxWidget(this, movingImage);
36 
37  mAvarageAccuracyLabel = new QLabel(QString(" "), this);
38 
39  mVerticalLayout->insertWidget(0, fixed);
40  mVerticalLayout->insertWidget(1, moving);
41  mVerticalLayout->insertWidget(2, mAvarageAccuracyLabel);
42 }
43 
45 {
46  if (this->isValid())
47  return QString("<b>Matrix fMm from moving to fixed image</b>");
48  else
49  return "<Invalid matrix>";
50 }
51 
53 {
54  return mServices->registration()->getMovingData() && mServices->registration()->getFixedData();
55 }
56 
58 {
59  if (!this->isValid()) // Check if fixed and moving data are defined
60  return Transform3D::Identity();
61 
62  Transform3D rMm = mServices->registration()->getMovingData()->get_rMd();
63  Transform3D rMf = mServices->registration()->getFixedData()->get_rMd();
64  Transform3D fMm = rMf.inv() * rMm;
65 
66  RegistrationHistoryPtr history = mServices->registration()->getMovingData()->get_rMd_History();
67  Transform3D init_rMd;
68  if(!history->getData().empty()) // Is vector with RegistrationTransforms empty ?
69  init_rMd = history->getData().front().mValue;
70  else
71  init_rMd = Transform3D::Identity();
72 
73  Transform3D current_rMd = history->getCurrentRegistration().mValue;
74  fMm = current_rMd * init_rMd.inv();
75 
76  return fMm;
77 }
78 
80 {
81  if (!this->isValid()) // Check if fixed and moving data are defined
82  return;
83 
84  Transform3D rMm = mServices->registration()->getMovingData()->get_rMd();
85 
86  RegistrationHistoryPtr history = mServices->registration()->getMovingData()->get_rMd_History();
87 
88  Transform3D init_rMd;
89 
90  if(!history->getData().empty()) // Is vector with RegistrationTransforms empty ?
91  init_rMd = history->getData().front().mValue;
92  else
93  init_rMd = Transform3D::Identity();
94 
95  Transform3D new_rMd = M * init_rMd;
96  Transform3D delta = new_rMd * rMm.inv();
97 
98  mServices->registration()->addImage2ImageRegistration(delta, "Manual Image");
99  this->updateAverageAccuracyLabel();
100 
101 }
102 
104 {
105  std::map<QString, LandmarkProperty> props = mServices->patient()->getLandmarkProperties();
106 
107  double sum = 0;
108  numActiveLandmarks = 0;
109  std::map<QString, LandmarkProperty>::iterator it = props.begin();
110  for (; it != props.end(); ++it)
111  {
112  if (!it->second.getActive()) //we don't want to take into account not active landmarks
113  continue;
114  QString uid = it->first;
115  double val = this->getAccuracy(uid);
116  if (!similar(val, 1000.0))
117  {
118  sum = sum + val;
119  numActiveLandmarks++;
120  }
121  }
122  if (numActiveLandmarks == 0)
123  return 1000.0;
124  return (sqrt(sum / (double)numActiveLandmarks));
125 }
126 
127 double ManualImage2ImageRegistrationWidget::getAccuracy(QString uid)
128 {
129  DataPtr fixedData = mServices->registration()->getFixedData();
130  if (!fixedData)
131  return 1000.0;
132  DataPtr movingData = mServices->registration()->getMovingData();
133  if (!movingData)
134  return 1000.0;
135 
136  Landmark masterLandmark = fixedData->getLandmarks()->getLandmarks()[uid];
137  Landmark targetLandmark = movingData->getLandmarks()->getLandmarks()[uid];
138  if (masterLandmark.getUid().isEmpty() || targetLandmark.getUid().isEmpty())
139  return 1000.0;
140 
141  Vector3D p_master_master = masterLandmark.getCoord();
142  Vector3D p_target_target = targetLandmark.getCoord();
143  Transform3D rMmaster = fixedData->get_rMd();
144  Transform3D rMtarget = movingData->get_rMd();
145 
146  Vector3D p_target_r = rMtarget.coord(p_target_target);
147  Vector3D p_master_r = rMmaster.coord(p_master_master);
148 
149  double targetPoint[3];
150  double masterPoint[3];
151  targetPoint[0] = p_target_r[0];
152  targetPoint[1] = p_target_r[1];
153  targetPoint[2] = p_target_r[2];
154  masterPoint[0] = p_master_r[0];
155  masterPoint[1] = p_master_r[1];
156  masterPoint[2] = p_master_r[2];
157 
158  return (vtkMath::Distance2BetweenPoints(targetPoint, masterPoint));
159 }
160 
161 void ManualImage2ImageRegistrationWidget::updateAverageAccuracyLabel()
162 {
163  QString fixedName;
164  QString movingName;
165  DataPtr fixedData = boost::dynamic_pointer_cast<Data>(mServices->registration()->getFixedData());
166  DataPtr movingData = boost::dynamic_pointer_cast<Data>(mServices->registration()->getMovingData());
167  if (fixedData)
168  fixedName = fixedData->getName();
169  if (movingData)
170  movingName = movingData->getName();
171 
172  int numberOfActiveLandmarks = 0;
173  if(this->isAverageAccuracyValid(numberOfActiveLandmarks))
174  {
175  mAvarageAccuracyLabel->setText(tr("Root mean square accuracy (Landmarks) %1 mm, calculated in %2 landmarks").
176  arg(this->getAverageAccuracy(numberOfActiveLandmarks), 0, 'f', 2).arg(numberOfActiveLandmarks));
177  mAvarageAccuracyLabel->setToolTip(QString("Root Mean Square landmark accuracy from target [%1] to fixed [%2].").
178  arg(movingName).arg(fixedName));
179  }
180  else
181  {
182  mAvarageAccuracyLabel->setText(" ");
183  mAvarageAccuracyLabel->setToolTip("");
184  }
185 }
186 
187 bool ManualImage2ImageRegistrationWidget::isAverageAccuracyValid(int& numberOfActiveLandmarks)
188 {
189  int numActiveLandmarks = 0;
190  this->getAverageAccuracy(numActiveLandmarks);
191  if(numActiveLandmarks < 1)
192  return false;
193  return true;
194 }
195 
196 
197 } // cx
QString getUid() const
Definition: cxLandmark.cpp:33
boost::shared_ptr< class RegistrationHistory > RegistrationHistoryPtr
Definition: cxDataManager.h:37
One landmark, or fiducial, coordinate.
Definition: cxLandmark.h:40
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
Composite widget for string selection.
boost::shared_ptr< class Data > DataPtr
boost::shared_ptr< class StringPropertyBase > StringPropertyBasePtr
virtual QString getName() const
Definition: cxData.cpp:69
boost::shared_ptr< class RegServices > RegServicesPtr
Definition: cxRegServices.h:20
Vector3D getCoord() const
Definition: cxLandmark.cpp:38
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
Superclass for all data objects.
Definition: cxData.h:89
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
ManualImage2ImageRegistrationWidget(RegServicesPtr services, QWidget *parent, QString objectName)
Namespace for all CustusX production code.