16 #include <vtkLandmarkTransform.h> 17 #include <vtkMatrix4x4.h> 18 #include <vtkPoints.h> 31 double FRENormalizationFactor,
34 const itk::Vector<double, 3> &translation);
43 vtkLandmarkTransform *landmarkTransform,
45 itk::Vector<double, 3> &translation);
48 : m_Threshold(1.0e-4),
49 m_MaxIterations(1000),
52 m_FRENormalizationFactor(1.0),
53 m_LandmarkTransform(vtkSmartPointer<vtkLandmarkTransform>::New())
85 const vnl_matrix_fixed<double, 3, 3> rotation_T = rotation.GetTranspose();
87 #pragma omp parallel for 88 for (
int i = 0; i < static_cast<int>(X.size()); ++i)
90 const Matrix3x3 w = rotation * X[i] * rotation_T;
100 double FRENormalizationFactor,
103 const itk::Vector<double, 3> &translation)
109 #pragma omp parallel for 110 for (
int i = 0; i < static_cast<int>(WeightMatrices.size()); ++i)
113 itk::Vector<double, 3> converted_MovingPoint;
115 X->GetPoint(i, point);
116 converted_MovingPoint[0] = point[0];
117 converted_MovingPoint[1] = point[1];
118 converted_MovingPoint[2] = point[2];
121 itk::Vector<double, 3> p = rotation * converted_MovingPoint + translation;
123 Y->GetPoint(i, point);
129 const itk::Vector<double, 3> D = WeightMatrices.at(i) * p;
131 FRE += (D[0] * D[0] + D[1] * D[1] + D[2] * D[2]);
134 FRE /= WeightMatrices.size();
135 FRE = FRENormalizationFactor * sqrt(FRE);
143 vtkLandmarkTransform *landmarkTransform,
145 itk::Vector<double, 3> &translation)
147 landmarkTransform->SetSourceLandmarks(X);
148 landmarkTransform->SetTargetLandmarks(Y);
149 landmarkTransform->SetModeToRigidBody();
150 landmarkTransform->Modified();
151 landmarkTransform->Update();
153 vtkMatrix4x4 *m = landmarkTransform->GetMatrix();
155 for (
int i = 0; i < 3; ++i)
156 for (
int j = 0; j < 3; ++j)
157 rotation[i][j] = m->GetElement(i, j);
159 translation[0] = m->GetElement(0, 3);
160 translation[1] = m->GetElement(1, 3);
161 translation[2] = m->GetElement(2, 3);
165 const WeightMatrixList &W,
166 itk::VariableSizeMatrix<double> &returnValue)
168 #pragma omp parallel for 169 for (
int i = 0; i < X->GetNumberOfPoints(); ++i)
171 unsigned int index = 3u * i;
173 X->GetPoint(i, point);
175 for (
int j = 0; j < 3; ++j)
177 returnValue[index][0] = -W.at(i)[j][1] * point[2] + W.at(i)[j][2] * point[1];
178 returnValue[index][1] = W.at(i)[j][0] * point[2] - W.at(i)[j][2] * point[0];
179 returnValue[index][2] = -W.at(i)[j][0] * point[1] + W.at(i)[j][1] * point[0];
180 returnValue[index][3] = W.at(i)[j][0];
181 returnValue[index][4] = W.at(i)[j][1];
182 returnValue[index][5] = W.at(i)[j][2];
190 const WeightMatrixList &W,
191 vnl_vector<double> &returnValue)
193 #pragma omp parallel for 194 for (
int i = 0; i < X->GetNumberOfPoints(); ++i)
196 unsigned int index = 3u * i;
204 M[0][0] = pY[0] - pX[0];
205 M[0][1] = pY[1] - pX[1];
206 M[0][2] = pY[2] - pX[2];
214 for (
unsigned int j = 0; j < 3; ++j)
216 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];
223 const CovarianceMatrixList &Sigma_X,
224 const CovarianceMatrixList &Sigma_Y,
227 Rotation &TransformationR,
228 Translation &TransformationT,
232 double FRE_identity = 0.0;
233 double FRE_isotropic_weighted = 0.0;
234 double initialFRE = 0.0;
237 Rotation initial_TransformationR;
238 initial_TransformationR.SetIdentity();
239 Translation initial_TransformationT;
240 initial_TransformationT.Fill(0.0);
243 vtkPoints *X_transformed = vtkPoints::New();
244 vtkPoints *X_transformedNew = vtkPoints::New();
245 vnl_vector<double> oldq;
246 itk::VariableSizeMatrix<double> iA;
247 vnl_vector<double> iB;
250 W.resize(X->GetNumberOfPoints());
251 X_transformed->SetNumberOfPoints(X->GetNumberOfPoints());
252 X_transformedNew->SetNumberOfPoints(X->GetNumberOfPoints());
253 iA.SetSize(3u * X->GetNumberOfPoints(), 6u);
254 iB.set_size(3u * X->GetNumberOfPoints());
260 MITK_DEBUG <<
"FRE for identity transform: " << FRE_identity;
266 TransformationR = initial_TransformationR;
267 TransformationT = initial_TransformationT;
270 FRE_isotropic_weighted =
272 MITK_DEBUG <<
"FRE for transform obtained with unweighted registration: " << FRE_isotropic_weighted;
275 if (FRE_isotropic_weighted < FRE_identity)
277 initialFRE = FRE_isotropic_weighted;
281 initialFRE = FRE_identity;
282 TransformationR.SetIdentity();
283 TransformationT.Fill(0.0);
284 initial_TransformationR.SetIdentity();
285 initial_TransformationT.Fill(0.0);
312 E_maker(X_transformed, Y, W, iB);
314 vnl_matrix_inverse<double> myInverse(iA.GetVnlMatrix());
315 vnl_vector<double> q = myInverse.pinverse(iB.size()) * iB;
322 itk::Vector<double, 3> delta_t;
327 Matrix3x3 delta_theta;
328 delta_theta[0][0] = 1;
329 delta_theta[0][1] = -q[2];
330 delta_theta[0][2] = q[1];
331 delta_theta[1][0] = q[2];
332 delta_theta[1][1] = 1;
333 delta_theta[1][2] = -q[0];
334 delta_theta[2][0] = -q[1];
335 delta_theta[2][1] = q[0];
336 delta_theta[2][2] = 1;
338 vnl_svd<double> svd_delta_theta(delta_theta.GetVnlMatrix());
344 for (
int i = 0; i < 3; ++i)
346 for (
int j = 0; j < 3; ++j)
348 U[i][j] = svd_delta_theta.U()[i][j];
349 V[i][j] = svd_delta_theta.V()[i][j];
353 Matrix3x3 delta_R = U * V.GetTranspose();
356 TransformationR = delta_R * TransformationR;
359 TransformationT = delta_R * TransformationT + delta_t;
368 vtkPoints *tmp = X_transformed;
369 X_transformed = X_transformedNew;
370 X_transformedNew = tmp;
372 }
while (config_change > Threshold && n < MaxIterations);
377 MITK_DEBUG <<
"FRE after algorithm (prior to check with initial): " << FRE;
380 if (initialFRE < FRE)
382 MITK_WARN <<
"FRE did not improve in anisotropic point registration function";
383 TransformationR = initial_TransformationR;
384 TransformationT = initial_TransformationT;
390 X_transformed->Delete();
391 X_transformedNew->Delete();
416 double sum[3] = {0.0, 0.0, 0.0};
417 double mean[3] = {0.0, 0.0, 0.0};
418 double pX[3] = {0.0, 0.0, 0.0};
419 double pX_new[3] = {0.0, 0.0, 0.0};
422 for (vtkIdType i = 0; i < X->GetNumberOfPoints(); ++i)
425 X_new->GetPoint(i, pX_new);
428 sum[0] += (pX_new[0] - pX[0]) * (pX_new[0] - pX[0]);
429 sum[1] += (pX_new[1] - pX[1]) * (pX_new[1] - pX[1]);
430 sum[2] += (pX_new[2] - pX[2]) * (pX_new[2] - pX[2]);
438 mean[0] /= X->GetNumberOfPoints();
439 mean[1] /= X->GetNumberOfPoints();
440 mean[2] /= X->GetNumberOfPoints();
442 const double us = sum[0] + sum[1] + sum[2];
445 sum[0] = sum[1] = sum[2] = 0.0;
447 for (vtkIdType i = 0; i < X->GetNumberOfPoints(); ++i)
451 sum[0] += (pX[0] - mean[0]) * (pX[0] - mean[0]);
452 sum[1] += (pX[1] - mean[1]) * (pX[1] - mean[1]);
453 sum[2] += (pX[2] - mean[2]) * (pX[2] - mean[2]);
456 const double ls = sum[0] + sum[1] + sum[2];
458 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.