Fraxinus  17.12-rc1
An IGT application
cxCenterlineRegistration.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) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
33 #include <vtkPointData.h>
34 #include <vtkPolyData.h>
35 #include <vtkPolyDataWriter.h>
36 #include <vtkCellArray.h>
37 #include <vtkMatrix4x4.h>
38 #include <vtkLinearTransform.h>
39 #include <vtkLandmarkTransform.h>
40 #include "cxTransform3D.h"
41 #include "cxVector3D.h"
42 #include "cxLogger.h"
43 #include <boost/math/special_functions/fpclassify.hpp> // isnan
44 #include "vtkCardinalSpline.h"
45 
46 typedef vtkSmartPointer<class vtkCardinalSpline> vtkCardinalSplinePtr;
47 
48 namespace cx
49 {
50 
51 
53 {
54  mFixedPointSet = PointSetType::New();
55  mMovingPointSet = PointSetType::New();
56  mRegistration = RegistrationType::New();
57  mTransform = TransformType::New();
58  MetricType::Pointer metric = MetricType::New();
59  mOptimizer = OptimizerType::New();
60  mOptimizer->SetUseCostFunctionGradient(false);
61  OptimizerType::ScalesType scales(mTransform->GetNumberOfParameters());
62 
63  unsigned long numberOfIterations = 2000;
64  double gradientTolerance = 1e-4;
65  double valueTolerance = 1e-4;
66  double epsilonFunction = 1e-5;
67 
68  UpdateScales(true,true,true,true,true,true);
69  mOptimizer->SetNumberOfIterations(numberOfIterations);
70  mOptimizer->SetValueTolerance(valueTolerance);
71  mOptimizer->SetGradientTolerance(gradientTolerance);
72  mOptimizer->SetEpsilonFunction(epsilonFunction);
73 
74  // Initialize transform
75  mTransform->SetIdentity();
76  mRegistration->SetInitialTransformParameters(mTransform->GetParameters());
77 
78  // Setup framework
79  mRegistration->SetMetric(metric);
80  mRegistration->SetOptimizer(mOptimizer);
81  mRegistration->SetTransform(mTransform);
82 
83 }
84 
85 
86 
87 vtkPointsPtr convertTovtkPoints(Eigen::MatrixXd positions)
88 {
89  vtkPointsPtr retval = vtkPointsPtr::New();
90 
91  for (unsigned i=0; i<positions.cols(); ++i)
92  {
93  retval->InsertNextPoint(positions(0,i), positions(1,i), positions(2,i));
94  }
95  return retval;
96 }
97 
98 void CenterlineRegistration::UpdateScales(bool xRot, bool yRot, bool zRot, bool xTrans, bool yTrans, bool zTrans)
99 {
100 
101  OptimizerType::ScalesType scales(mTransform->GetNumberOfParameters());
102  const double translationScale = 40.0; // dynamic range of translations
103  const double rotationScale = 0.3; // dynamic range of rotations
104 
105  if (xRot)
106  scales[0] = 1.0 / rotationScale;
107  else
108  scales[0] = 1e50;
109  if (yRot)
110  scales[1] = 1.0 / rotationScale;
111  else
112  scales[1] = 1e50;
113  if (zRot)
114  scales[2] = 1.0 / rotationScale;
115  else
116  scales[2] = 1e50;
117  if (xTrans)
118  scales[3] = 1.0 / translationScale;
119  else
120  scales[3] = 1e50;
121  if (yTrans)
122  scales[4] = 1.0 / translationScale;
123  else
124  scales[4] = 1e50;
125  if (zTrans)
126  scales[5] = 1.0 / translationScale;
127  else
128  scales[5] = 1e50;
129 
130  mOptimizer->SetScales(scales);
131  mRegistration->SetOptimizer(mOptimizer);
132 
133  std::cout << "Update scales: "
134  << mRegistration->GetOptimizer()->GetScales()
135  << scales
136  << std::endl;
137 
138 }
139 
140 
142 {
143  int numberOfInputPoints = centerline->GetNumberOfPoints();
144  int controlPointFactor = 10;
145  int numberOfControlPoints = numberOfInputPoints / controlPointFactor;
146  if (numberOfControlPoints < 10)
147  numberOfControlPoints = std::min(numberOfInputPoints,10);
148 
149  int numberOfOutputPoints = std::max(numberOfInputPoints, 100); //interpolate to at least 100 output points
150  vtkPointsPtr newCenterline = vtkPointsPtr::New();;
151 
152  vtkCardinalSplinePtr splineX = vtkSmartPointer<vtkCardinalSpline>::New();
153  vtkCardinalSplinePtr splineY = vtkSmartPointer<vtkCardinalSpline>::New();
154  vtkCardinalSplinePtr splineZ = vtkSmartPointer<vtkCardinalSpline>::New();
155 
156  if (numberOfControlPoints >= 2)
157  {
158  //add control points to spline
159  for(int i=0; i<numberOfControlPoints; i++)
160  {
161  int indexP = (i*numberOfInputPoints)/numberOfControlPoints;
162  double p[3];
163  centerline->GetPoint(indexP,p);
164  int indexSpline = (i*numberOfOutputPoints)/numberOfControlPoints;
165  splineX->AddPoint( indexSpline, p[0] );
166  splineY->AddPoint( indexSpline, p[1] );
167  splineZ->AddPoint( indexSpline, p[2] );
168  //std::cout << "spline point: " << "(" << indexSpline << ") " << p[0] << " " << p[1] << " " << p[2] << std::endl;
169  }
170 
171  //Always add the last point to complete spline
172  double p[3];
173  centerline->GetPoint( numberOfInputPoints-1, p );
174  splineX->AddPoint( numberOfOutputPoints-1, p[0] );
175  splineY->AddPoint( numberOfOutputPoints-1, p[1] );
176  splineZ->AddPoint( numberOfOutputPoints-1, p[2] );
177  //std::cout << "spline point: " << "(" << numberOfOutputPoints-1 << ") " << p[0] << " " << p[1] << " " << p[2] << std::endl;
178 
179  //evaluate spline - get smoothed positions
180  for(int i=0; i<numberOfOutputPoints; i++)
181  {
182  double splineParameter = i;
183  newCenterline->InsertNextPoint(splineX->Evaluate(splineParameter),
184  splineY->Evaluate(splineParameter),
185  splineZ->Evaluate(splineParameter));
186  }
187  }
188  else
189  return centerline;
190 
191  return newCenterline;
192 }
193 
195 {
196 
197  vtkPointsPtr processedPositions = vtkPointsPtr::New();
198  int N = centerline->GetNumberOfPoints();
199  Eigen::MatrixXd CLpoints(3,N);
200  for(vtkIdType i = 0; i < N; i++)
201  {
202  double p[3];
203  centerline->GetPoint(i,p);
204  Vector3D pos;
205  pos(0) = p[0]; pos(1) = p[1]; pos(2) = p[2];
206  pos = rMd.coord(pos);
207  processedPositions->InsertNextPoint(pos[0],pos[1],pos[2]);
208  }
209 
210  //sort positions?
211  processedPositions = smoothPositions(processedPositions);
212 
213  return processedPositions;
214 }
215 
217 {
218  vtkPointsPtr loggedPositions = vtkPointsPtr::New();
219 
220  for(TimedTransformMap::iterator iter=trackingData_prMt.begin();
221  iter!=trackingData_prMt.end();++iter)
222  {
223  Transform3D prMt = iter->second;
224  Vector3D pos = prMt.matrix().block<3,1> (0, 3);
225  pos = rMpr.coord(pos);
226  loggedPositions->InsertNextPoint(pos[0],pos[1],pos[2]);
227  }
228 
229  return loggedPositions;
230 }
231 
233 {
234  mFixedPointSet->Initialize(); // Clear previous pointset
235 // PointsContainerPtr itkPoints = mFixedPointSet->GetPoints();
236  PointsContainerPtr itkPoints = PointsContainer::New();
237  PointType point;
238 
239  for(vtkIdType n=0;n<vtkPoints->GetNumberOfPoints();n++)
240  {
241  double temp_Point[3];
242  vtkPoints->GetPoint(n, temp_Point);
243  point[0] = temp_Point[0];
244  point[1] = temp_Point[1];
245  point[2] = temp_Point[2];
246  Vector3D vPoint(temp_Point[0], temp_Point[1], temp_Point[2]);
247  itkPoints->InsertElement(n,point);
248  }
249  mFixedPointSet->SetPoints(itkPoints);
250 }
251 
253 {
254  mMovingPointSet->Initialize();
255  PointsContainerPtr itkPoints = PointsContainer::New();
256  PointType point;
257 
258  for(vtkIdType n=0;n<vtkPoints->GetNumberOfPoints();n++)
259  {
260  double temp_Point[3];
261  vtkPoints->GetPoint(n, temp_Point);
262  Vector3D vPoint(temp_Point[0], temp_Point[1], temp_Point[2]);
263  point[0] = temp_Point[0];
264  point[1] = temp_Point[1];
265  point[2] = temp_Point[2];
266  itkPoints->InsertElement(n,point);
267  }
268  mMovingPointSet->SetPoints(itkPoints);
269 }
270 
272 {
273  mRegistration->SetFixedPointSet(mFixedPointSet);
274  mRegistration->SetMovingPointSet(mMovingPointSet);
275 
276  typedef itk::Matrix<double,3,3> MatrixType;
277  typedef TransformType::OffsetType TranslateVector;
278  MatrixType initMatrix;
279  TranslateVector initTranslation;
280 
281  // Set initial rotation
282  for(int i=0; i<3; i++)
283  for(int j=0;j<3;j++) {
284  double element = init_transform(i,j);
285  initMatrix(i,j) = element;
286  }
287 
288  // Set initial translation
289  initTranslation[0] = init_transform(0,3);
290  initTranslation[1] = init_transform(1,3);
291  initTranslation[2] = init_transform(2,3);
292 
293  mTransform->SetMatrix(initMatrix, 1e-5);
294  mTransform->SetTranslation(initTranslation);
295 
296  mRegistration->SetInitialTransformParameters(mTransform->GetParameters());
297 
298  try
299  {
300  mRegistration->Update();
301  }
302  catch (itk::ExceptionObject &exp)
303  {
304  std::cout << "CenterlineRegMethod - Exception caught ! " << std::endl;
305  std::cout << exp << std::endl;
306  }
307 
308  RegistrationType::ParametersType finalParameters =
309  mRegistration->GetLastTransformParameters();
310 
311  TransformType::MatrixType regMatrix = mTransform->GetMatrix();
312 
313  for(int i=0; i<3; i++)
314  for(int j=0;j<3;j++) {
315  double element = regMatrix(i,j);
316  mResultTransform(i,j) = element;
317  }
318 
319  mResultTransform(0,3) = finalParameters(3);
320  mResultTransform(1,3) = finalParameters(4);
321  mResultTransform(2,3) = finalParameters(5);
322 
323  mRegistrationUpdated = true;
324 
325  return Transform3D(mResultTransform);
326 }
327 
328 
330 {
331 
332  vtkPointsPtr centerlinePoints = processCenterline(centerline, rMd);
333 
334  SetFixedPoints( centerlinePoints );
335  SetMovingPoints( ConvertTrackingDataToVTK(trackingData_prMt, old_rMpr) );
336 
337  Transform3D rMpr = FullRegisterMoving(Transform3D::Identity());
338 
339  std::cout << "rMpr : " << std::endl;
340  std::cout << rMpr << std::endl;
341 
342  return rMpr;
343 }
344 
346 {
347 
348 }
349 
350 
351 
352 }//namespace cx
vtkPointsPtr processCenterline(vtkPolyDataPtr centerline, Transform3D rMd)
vtkPointsPtr ConvertTrackingDataToVTK(TimedTransformMap trackingData_prMt, Transform3D rMpr)
PointSetType::PointType PointType
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
void SetMovingPoints(vtkPointsPtr points)
vtkSmartPointer< vtkPoints > vtkPointsPtr
Transform3D runCenterlineRegistration(vtkPolyDataPtr centerline, Transform3D rMd, TimedTransformMap trackingData_prMt, Transform3D old_rMpr)
vtkSmartPointer< class vtkCardinalSpline > vtkCardinalSplinePtr
Definition: cxAccusurf.cpp:17
vtkPointsPtr smoothPositions(vtkPointsPtr centerline)
vtkPointsPtr convertTovtkPoints(Eigen::MatrixXd positions)
vtkSmartPointer< class vtkCardinalSpline > vtkCardinalSplinePtr
Transform3D FullRegisterMoving(Transform3D init_transform)
vtkSmartPointer< vtkPolyData > vtkPolyDataPtr
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:63
PointSetType::PointsContainerPointer PointsContainerPtr
void UpdateScales(bool xRot, bool yRot, bool zRot, bool xTrans, bool yTrans, bool zTrans)
void SetFixedPoints(vtkPointsPtr points)
std::map< double, Transform3D > TimedTransformMap
Namespace for all CustusX production code.