20 #include <vtkLandmarkTransform.h>
21 #include <vtkMatrix4x4.h>
22 #include <vtkPoints.h>
35 double FRENormalizationFactor,
38 const itk::Vector<double, 3> &translation);
47 vtkLandmarkTransform *landmarkTransform,
49 itk::Vector<double, 3> &translation);
52 : m_Threshold(1.0e-4),
53 m_MaxIterations(1000),
56 m_FRENormalizationFactor(1.0),
57 m_LandmarkTransform(vtkSmartPointer<vtkLandmarkTransform>::
New())
63 m_FixedPointSet =
nullptr;
64 m_MovingPointSet =
nullptr;
65 m_LandmarkTransform =
nullptr;
70 WeightedPointRegister(m_MovingPointSet,
72 m_CovarianceMatricesMoving,
73 m_CovarianceMatricesFixed,
89 const vnl_matrix_fixed<double, 3, 3> rotation_T = rotation.GetTranspose();
91 #pragma omp parallel for
92 for (
int i = 0; i < static_cast<int>(X.size()); ++i)
94 const Matrix3x3 w = rotation * X[i] * rotation_T;
104 double FRENormalizationFactor,
107 const itk::Vector<double, 3> &translation)
113 #pragma omp parallel for reduction(+ : FRE)
114 for (
int i = 0; i < static_cast<int>(WeightMatrices.size()); ++i)
117 itk::Vector<double, 3> converted_MovingPoint;
119 X->GetPoint(i, point);
120 converted_MovingPoint[0] = point[0];
121 converted_MovingPoint[1] = point[1];
122 converted_MovingPoint[2] = point[2];
125 itk::Vector<double, 3> p = rotation * converted_MovingPoint + translation;
127 Y->GetPoint(i, point);
133 const itk::Vector<double, 3> D = WeightMatrices.at(i) * p;
134 FRE += (D[0] * D[0] + D[1] * D[1] + D[2] * D[2]);
137 FRE /= WeightMatrices.size();
138 FRE = FRENormalizationFactor * sqrt(FRE);
146 vtkLandmarkTransform *landmarkTransform,
148 itk::Vector<double, 3> &translation)
150 landmarkTransform->SetSourceLandmarks(X);
151 landmarkTransform->SetTargetLandmarks(Y);
152 landmarkTransform->SetModeToRigidBody();
153 landmarkTransform->Modified();
154 landmarkTransform->Update();
156 vtkMatrix4x4 *m = landmarkTransform->GetMatrix();
158 for (
int i = 0; i < 3; ++i)
159 for (
int j = 0; j < 3; ++j)
160 rotation[i][j] = m->GetElement(i, j);
162 translation[0] = m->GetElement(0, 3);
163 translation[1] = m->GetElement(1, 3);
164 translation[2] = m->GetElement(2, 3);
168 const WeightMatrixList &W,
169 itk::VariableSizeMatrix<double> &returnValue)
171 #pragma omp parallel for
172 for (vtkIdType i = 0; i < X->GetNumberOfPoints(); ++i)
174 unsigned int index = 3u * i;
176 X->GetPoint(i, point);
178 for (
int j = 0; j < 3; ++j)
180 returnValue[index][0] = -W.at(i)[j][1] * point[2] + W.at(i)[j][2] * point[1];
181 returnValue[index][1] = W.at(i)[j][0] * point[2] - W.at(i)[j][2] * point[0];
182 returnValue[index][2] = -W.at(i)[j][0] * point[1] + W.at(i)[j][1] * point[0];
183 returnValue[index][3] = W.at(i)[j][0];
184 returnValue[index][4] = W.at(i)[j][1];
185 returnValue[index][5] = W.at(i)[j][2];
193 const WeightMatrixList &W,
194 vnl_vector<double> &returnValue)
196 #pragma omp parallel for
197 for (vtkIdType i = 0; i < X->GetNumberOfPoints(); ++i)
199 unsigned int index = 3u * i;
207 M[0][0] = pY[0] - pX[0];
208 M[0][1] = pY[1] - pX[1];
209 M[0][2] = pY[2] - pX[2];
217 for (
unsigned int j = 0; j < 3; ++j)
219 returnValue[index + j] = W.at(i)[j][0] * M[j][0] + W.at(i)[j][1] * M[j][1] + W.at(i)[j][2] * M[j][2];
226 const CovarianceMatrixList &Sigma_X,
227 const CovarianceMatrixList &Sigma_Y,
230 Rotation &TransformationR,
231 Translation &TransformationT,
235 double FRE_identity = 0.0;
236 double FRE_isotropic_weighted = 0.0;
237 double initialFRE = 0.0;
240 Rotation initial_TransformationR;
241 initial_TransformationR.SetIdentity();
242 Translation initial_TransformationT;
243 initial_TransformationT.Fill(0.0);
248 vnl_vector<double> oldq;
249 itk::VariableSizeMatrix<double> iA;
250 vnl_vector<double> iB;
253 W.resize(X->GetNumberOfPoints());
254 X_transformed->SetNumberOfPoints(X->GetNumberOfPoints());
255 X_transformedNew->SetNumberOfPoints(X->GetNumberOfPoints());
256 iA.SetSize(3u * X->GetNumberOfPoints(), 6u);
257 iB.set_size(3u * X->GetNumberOfPoints());
261 X, Y, Sigma_X, Sigma_Y, m_FRENormalizationFactor, W, initial_TransformationR, initial_TransformationT);
263 MITK_DEBUG <<
"FRE for identity transform: " << FRE_identity;
269 TransformationR = initial_TransformationR;
270 TransformationT = initial_TransformationT;
273 FRE_isotropic_weighted =
274 ComputeWeightedFRE(X, Y, Sigma_X, Sigma_Y, m_FRENormalizationFactor, W, TransformationR, TransformationT);
275 MITK_DEBUG <<
"FRE for transform obtained with unweighted registration: " << FRE_isotropic_weighted;
278 if (FRE_isotropic_weighted < FRE_identity)
280 initialFRE = FRE_isotropic_weighted;
284 initialFRE = FRE_identity;
285 TransformationR.SetIdentity();
286 TransformationT.Fill(0.0);
287 initial_TransformationR.SetIdentity();
288 initial_TransformationT.Fill(0.0);
314 C_maker(X_transformed, W, iA);
315 E_maker(X_transformed, Y, W, iB);
317 vnl_matrix_inverse<double> myInverse(iA.GetVnlMatrix());
318 vnl_vector<double> q = myInverse.pinverse(iB.size()) * iB;
325 itk::Vector<double, 3> delta_t;
330 Matrix3x3 delta_theta;
331 delta_theta[0][0] = 1;
332 delta_theta[0][1] = -q[2];
333 delta_theta[0][2] = q[1];
334 delta_theta[1][0] = q[2];
335 delta_theta[1][1] = 1;
336 delta_theta[1][2] = -q[0];
337 delta_theta[2][0] = -q[1];
338 delta_theta[2][1] = q[0];
339 delta_theta[2][2] = 1;
341 vnl_svd<double> svd_delta_theta(delta_theta.GetVnlMatrix());
347 for (
int i = 0; i < 3; ++i)
349 for (
int j = 0; j < 3; ++j)
351 U[i][j] = svd_delta_theta.U()[i][j];
352 V[i][j] = svd_delta_theta.V()[i][j];
356 Matrix3x3 delta_R = U * V.GetTranspose();
359 TransformationR = delta_R * TransformationR;
362 TransformationT = delta_R * TransformationT + delta_t;
367 config_change = CalculateConfigChange(X_transformed, X_transformedNew);
371 vtkPoints *tmp = X_transformed;
372 X_transformed = X_transformedNew;
373 X_transformedNew = tmp;
375 }
while (config_change > Threshold && n < MaxIterations);
378 FRE =
ComputeWeightedFRE(X, Y, Sigma_X, Sigma_Y, m_FRENormalizationFactor, W, TransformationR, TransformationT);
380 MITK_DEBUG <<
"FRE after algorithm (prior to check with initial): " << FRE;
383 if (initialFRE < FRE)
385 MITK_WARN <<
"FRE did not improve in anisotropic point registration function";
386 TransformationR = initial_TransformationR;
387 TransformationT = initial_TransformationT;
393 X_transformed->Delete();
394 X_transformedNew->Delete();
399 m_MovingPointSet = p;
404 m_CovarianceMatricesMoving = matrices;
414 m_CovarianceMatricesFixed = matrices;
419 double sum[3] = {0.0, 0.0, 0.0};
420 double mean[3] = {0.0, 0.0, 0.0};
421 double pX[3] = {0.0, 0.0, 0.0};
422 double pX_new[3] = {0.0, 0.0, 0.0};
425 for (vtkIdType i = 0; i < X->GetNumberOfPoints(); ++i)
428 X_new->GetPoint(i, pX_new);
431 sum[0] += (pX_new[0] - pX[0]) * (pX_new[0] - pX[0]);
432 sum[1] += (pX_new[1] - pX[1]) * (pX_new[1] - pX[1]);
433 sum[2] += (pX_new[2] - pX[2]) * (pX_new[2] - pX[2]);
441 mean[0] /= X->GetNumberOfPoints();
442 mean[1] /= X->GetNumberOfPoints();
443 mean[2] /= X->GetNumberOfPoints();
445 const double us = sum[0] + sum[1] + sum[2];
448 sum[0] = sum[1] = sum[2] = 0.0;
450 for (vtkIdType i = 0; i < X->GetNumberOfPoints(); ++i)
454 sum[0] += (pX[0] - mean[0]) * (pX[0] - mean[0]);
455 sum[1] += (pX[1] - mean[1]) * (pX[1] - mean[1]);
456 sum[2] += (pX[2] - mean[2]) * (pX[2] - mean[2]);
459 const double ls = sum[0] + sum[1] + sum[2];
461 return sqrt(us / ls);
static void TransformPoints(vtkPoints *src, vtkPoints *dst, const Rotation &rotation, const Translation &translation)
Transforms a point cloud with a Rotation and Translation.
static WeightMatrix CalculateWeightMatrix(const CovarianceMatrix &sigma_X, const CovarianceMatrix &sigma_Y)
Method that computes a WeightMatrix with two CovarianceMatrices.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.