ANIMA  4.0
animaDenseSVFTransformAgregator.hxx
Go to the documentation of this file.
1 #pragma once
3 
7 
8 #include <animaMatrixLogExp.h>
9 #include <itkTimeProbe.h>
10 
11 namespace anima
12 {
13 
14 template <unsigned int NDimensions>
15 DenseSVFTransformAgregator <NDimensions>::
16 DenseSVFTransformAgregator() : Superclass()
17 {
20 
21  m_NeighborhoodHalfSize = (unsigned int)floor(m_ExtrapolationSigma * 3);
24 
25  m_NumberOfThreads = itk::MultiThreaderBase::GetGlobalDefaultNumberOfThreads();
26 }
27 
28 template <unsigned int NDimensions>
29 bool
32 {
33  this->SetUpToDate(false);
34 
35  if (this->GetInputWeights().size() != this->GetInputTransforms().size())
36  return false;
37 
39  return false;
40 
41  itk::TimeProbe tmpTime;
42  tmpTime.Start();
43  switch (this->GetInputTransformType())
44  {
47  this->estimateSVFFromTranslations();
48  this->SetUpToDate(true);
49  break;
50 
51  case Superclass::RIGID:
52  this->estimateSVFFromRigidTransforms();
53  this->SetUpToDate(true);
54  break;
55 
56  case Superclass::AFFINE:
57  default:
58  this->estimateSVFFromAffineTransforms();
59  this->SetUpToDate(true);
60  break;
61  }
62 
63  tmpTime.Stop();
64  if (this->GetVerboseAgregation())
65  std::cout << "Agregation performed in " << tmpTime.GetTotal() << std::endl;
66 
67  return true;
68 }
69 
70 template <unsigned int NDimensions>
71 void
73 estimateSVFFromTranslations()
74 {
75  const unsigned int NDegreesFreedom = NDimensions;
76  unsigned int nbPts = this->GetInputRegions().size();
77  VelocityFieldPointer velocityField = VelocityFieldType::New();
78  velocityField->Initialize();
79 
80  velocityField->SetRegions (m_LargestRegion);
81  velocityField->SetSpacing (m_Spacing);
82  velocityField->SetOrigin (m_Origin);
83  velocityField->SetDirection (m_Direction);
84  velocityField->Allocate();
85 
86  VelocityFieldPixelType zeroDisp;
87  zeroDisp.Fill(0);
88  itk::ImageRegionIterator < VelocityFieldType > svfIterator(velocityField,m_LargestRegion);
89  while (!svfIterator.IsAtEnd())
90  {
91  svfIterator.Set(zeroDisp);
92  ++svfIterator;
93  }
94 
95  WeightImagePointer weights = WeightImageType::New();
96  weights->Initialize();
97 
98  weights->SetRegions (m_LargestRegion);
99  weights->SetSpacing (m_Spacing);
100  weights->SetOrigin (m_Origin);
101  weights->SetDirection (m_Direction);
102  weights->Allocate();
103  weights->FillBuffer(0);
104 
105  ParametersType tmpParams(NDimensions);
106  VelocityFieldPixelType curDisp;
107  VelocityFieldIndexType posIndex;
108 
109  for (unsigned int i = 0;i < nbPts;++i)
110  {
112  tmpParams = this->GetInputTransform(i)->GetParameters();
113  else
114  {
115  BaseMatrixTransformType *tmpTr = dynamic_cast <BaseMatrixTransformType *> (this->GetInputTransform(i));
116  for (unsigned int j = 0;j < NDimensions;++j)
117  tmpParams[j] = tmpTr->GetOffset()[j];
118  }
119  double tmpWeight = this->GetInputWeight(i);
120 
121  weights->TransformPhysicalPointToIndex(this->GetInputOrigin(i),posIndex);
122  for (unsigned int j = 0;j < NDimensions;++j)
123  curDisp[j] = tmpParams[j];
124 
125  velocityField->SetPixel(posIndex,curDisp);
126  weights->SetPixel(posIndex,tmpWeight);
127  }
128 
130  typename SVFMEstimateType::Pointer fieldSmoother = SVFMEstimateType::New();
131 
132  fieldSmoother->SetInput(velocityField);
133  fieldSmoother->SetWeightImage(weights);
134  fieldSmoother->SetFluidSigma(m_ExtrapolationSigma);
135  fieldSmoother->SetDistanceBoundary(m_DistanceBoundary);
136  fieldSmoother->SetMEstimateFactor(m_OutlierRejectionSigma);
137 
138  fieldSmoother->SetConvergenceThreshold(m_MEstimateConvergenceThreshold);
139  fieldSmoother->SetMaxNumIterations(100);
140 
141  fieldSmoother->SetNumberOfWorkUnits(m_NumberOfThreads);
142 
143  fieldSmoother->Update();
144 
145  velocityField = fieldSmoother->GetOutput();
146  velocityField->DisconnectPipeline();
147 
148  // Create the final transform
149  typename BaseOutputTransformType::Pointer resultTransform = BaseOutputTransformType::New();
150  resultTransform->SetIdentity();
151  resultTransform->SetParametersAsVectorField(velocityField.GetPointer());
152 
153  this->SetOutput(resultTransform);
154 }
155 
156 template <unsigned int NDimensions>
157 void
159 estimateSVFFromRigidTransforms()
160 {
161  const unsigned int NDegreesFreedom = NDimensions * (NDimensions + 1) / 2;
162  typedef itk::Image < itk::Vector <ScalarType, NDegreesFreedom>, NDimensions > RigidFieldType;
163  typedef typename RigidFieldType::Pointer RigidFieldPointer;
164  typedef itk::Vector <ScalarType, NDegreesFreedom> RigidVectorType;
165 
166  unsigned int nbPts = this->GetInputRegions().size();
167  RigidFieldPointer rigidField = RigidFieldType::New();
168  rigidField->Initialize();
169 
170  rigidField->SetRegions (m_LargestRegion);
171  rigidField->SetSpacing (m_Spacing);
172  rigidField->SetOrigin (m_Origin);
173  rigidField->SetDirection (m_Direction);
174  rigidField->Allocate();
175 
176  RigidVectorType zeroDisp;
177  zeroDisp.Fill(0);
178  itk::ImageRegionIterator < RigidFieldType > rigidIterator(rigidField,m_LargestRegion);
179  while (!rigidIterator.IsAtEnd())
180  {
181  rigidIterator.Set(zeroDisp);
182  ++rigidIterator;
183  }
184 
185  WeightImagePointer weights = WeightImageType::New();
186  weights->Initialize();
187 
188  weights->SetRegions (m_LargestRegion);
189  weights->SetSpacing (m_Spacing);
190  weights->SetOrigin (m_Origin);
191  weights->SetDirection (m_Direction);
192  weights->Allocate();
193  weights->FillBuffer(0);
194 
195  RigidVectorType curLog;
196  VelocityFieldIndexType posIndex;
197 
198  vnl_matrix <InternalScalarType> tmpMatrix(NDimensions+1,NDimensions+1,0);
199  tmpMatrix(NDimensions,NDimensions) = 1;
200 
201  typedef anima::LogRigid3DTransform <InternalScalarType> LogRigidTransformType;
202 
203  for (unsigned int i = 0;i < nbPts;++i)
204  {
205  double tmpWeight = this->GetInputWeight(i);
206  weights->TransformPhysicalPointToIndex(this->GetInputOrigin(i),posIndex);
207 
208  LogRigidTransformType *tmpTrsf = (LogRigidTransformType *)this->GetInputTransform(i);
209  rigidField->SetPixel(posIndex,tmpTrsf->GetLogVector());
210  weights->SetPixel(posIndex,tmpWeight);
211  }
212 
214  typename SVFMEstimateType::Pointer fieldSmoother = SVFMEstimateType::New();
215 
216  fieldSmoother->SetInput(rigidField);
217  fieldSmoother->SetWeightImage(weights);
218  fieldSmoother->SetFluidSigma(m_ExtrapolationSigma);
219  fieldSmoother->SetDistanceBoundary(m_DistanceBoundary);
220  fieldSmoother->SetMEstimateFactor(m_OutlierRejectionSigma);
221 
222  fieldSmoother->SetConvergenceThreshold(m_MEstimateConvergenceThreshold);
223  fieldSmoother->SetMaxNumIterations(100);
224 
225  fieldSmoother->SetNumberOfWorkUnits(m_NumberOfThreads);
226 
227  fieldSmoother->Update();
228 
229  rigidField = fieldSmoother->GetOutput();
230  rigidField->DisconnectPipeline();
231 
232  VelocityFieldPointer velocityField = VelocityFieldType::New();
233  velocityField->Initialize();
234 
235  velocityField->SetRegions (m_LargestRegion);
236  velocityField->SetSpacing (m_Spacing);
237  velocityField->SetOrigin (m_Origin);
238  velocityField->SetDirection (m_Direction);
239  velocityField->Allocate();
240 
241  itk::ImageRegionIteratorWithIndex < VelocityFieldType > svfIterator(velocityField,m_LargestRegion);
242  tmpMatrix.fill(0);
243  VelocityFieldIndexType curIndex;
244  VelocityFieldPointType curPoint;
245  VelocityFieldPixelType curDisp;
246 
247  rigidIterator = itk::ImageRegionIterator < RigidFieldType > (rigidField,m_LargestRegion);
248  while (!svfIterator.IsAtEnd())
249  {
250  curLog = rigidIterator.Get();
251 
252  unsigned int pos = 0;
253  for (unsigned int j = 0;j < NDimensions;++j)
254  for (unsigned int k = j+1;k < NDimensions;++k)
255  {
256  tmpMatrix(j,k) = curLog[pos];
257  tmpMatrix(k,j) = - curLog[pos];
258  ++pos;
259  }
260 
261  for (unsigned int j = 0;j < NDimensions;++j)
262  {
263  tmpMatrix(j,NDimensions) = curLog[pos];
264  ++pos;
265  }
266 
267  curIndex = svfIterator.GetIndex();
268  velocityField->TransformIndexToPhysicalPoint(curIndex,curPoint);
269  for (unsigned int i = 0;i < NDimensions;++i)
270  {
271  curDisp[i] = tmpMatrix(i,NDimensions);
272  for (unsigned int j = 0;j < NDimensions;++j)
273  curDisp[i] += tmpMatrix(i,j) * curPoint[j];
274  }
275 
276  svfIterator.Set(curDisp);
277 
278  ++rigidIterator;
279  ++svfIterator;
280  }
281 
282  // Create the final transform
283  typename BaseOutputTransformType::Pointer resultTransform = BaseOutputTransformType::New();
284  resultTransform->SetIdentity();
285  resultTransform->SetParametersAsVectorField(velocityField.GetPointer());
286 
287  this->SetOutput(resultTransform);
288 }
289 
290 template <unsigned int NDimensions>
291 void
293 estimateSVFFromAffineTransforms()
294 {
295  const unsigned int NDegreesFreedom = NDimensions * (NDimensions + 1);
296  typedef itk::Image < itk::Vector <ScalarType, NDegreesFreedom>, NDimensions > AffineFieldType;
297  typedef typename AffineFieldType::Pointer AffineFieldPointer;
298  typedef itk::Vector <ScalarType, NDegreesFreedom> AffineVectorType;
299 
300  unsigned int nbPts = this->GetInputRegions().size();
301  AffineFieldPointer affineField = AffineFieldType::New();
302  affineField->Initialize();
303 
304  affineField->SetRegions (m_LargestRegion);
305  affineField->SetSpacing (m_Spacing);
306  affineField->SetOrigin (m_Origin);
307  affineField->SetDirection (m_Direction);
308  affineField->Allocate();
309 
310  AffineVectorType zeroDisp;
311  zeroDisp.Fill(0);
312  itk::ImageRegionIterator < AffineFieldType > affineIterator(affineField,m_LargestRegion);
313  while (!affineIterator.IsAtEnd())
314  {
315  affineIterator.Set(zeroDisp);
316  ++affineIterator;
317  }
318 
319  WeightImagePointer weights = WeightImageType::New();
320  weights->Initialize();
321 
322  weights->SetRegions (m_LargestRegion);
323  weights->SetSpacing (m_Spacing);
324  weights->SetOrigin (m_Origin);
325  weights->SetDirection (m_Direction);
326  weights->Allocate();
327  weights->FillBuffer(0);
328 
329  AffineVectorType curLog;
330  VelocityFieldIndexType posIndex;
331 
332  vnl_matrix <InternalScalarType> tmpMatrix(NDimensions+1,NDimensions+1,0);
333  tmpMatrix(NDimensions,NDimensions) = 1;
334  std::vector < AffineVectorType > logVectors(nbPts);
335 
337  {
339 
340  MatrixLoggerFilterType *logFilter = new MatrixLoggerFilterType;
341  logFilter->SetInput(this->GetInputTransforms());
342  logFilter->SetNumberOfWorkUnits(m_NumberOfThreads);
343  logFilter->SetUseRigidTransforms(false);
344 
345  logFilter->Update();
346  logVectors = logFilter->GetOutput();
347 
348  delete logFilter;
349  }
350  else
351  {
353  DistoTrsfType *tmpTrsf;
354  for (unsigned int i = 0;i < nbPts;++i)
355  {
356  tmpTrsf = dynamic_cast <DistoTrsfType *> (this->GetInputTransform(i));
357  logVectors[i] = tmpTrsf->GetLogVector();
358  }
359  }
360 
361  for (unsigned int i = 0;i < nbPts;++i)
362  {
363  double tmpWeight = this->GetInputWeight(i);
364  weights->TransformPhysicalPointToIndex(this->GetInputOrigin(i),posIndex);
365 
366  if (std::isnan(logVectors[i][0]))
367  {
368  tmpWeight = 0;
369  logVectors[i].Fill(0);
370  }
371 
372  affineField->SetPixel(posIndex,logVectors[i]);
373  weights->SetPixel(posIndex,tmpWeight);
374  }
375 
377  typename SVFMEstimateType::Pointer fieldSmoother = SVFMEstimateType::New();
378 
379  fieldSmoother->SetInput(affineField);
380  fieldSmoother->SetWeightImage(weights);
381  fieldSmoother->SetFluidSigma(m_ExtrapolationSigma);
382  fieldSmoother->SetDistanceBoundary(m_DistanceBoundary);
383  fieldSmoother->SetMEstimateFactor(m_OutlierRejectionSigma);
384 
385  fieldSmoother->SetConvergenceThreshold(m_MEstimateConvergenceThreshold);
386  fieldSmoother->SetMaxNumIterations(100);
387 
388  fieldSmoother->SetNumberOfWorkUnits(m_NumberOfThreads);
389 
390  fieldSmoother->Update();
391 
392  affineField = fieldSmoother->GetOutput();
393  affineField->DisconnectPipeline();
394 
395  VelocityFieldPointer velocityField = VelocityFieldType::New();
396  velocityField->Initialize();
397 
398  velocityField->SetRegions (m_LargestRegion);
399  velocityField->SetSpacing (m_Spacing);
400  velocityField->SetOrigin (m_Origin);
401  velocityField->SetDirection (m_Direction);
402  velocityField->Allocate();
403 
404  itk::ImageRegionIteratorWithIndex < VelocityFieldType > svfIterator(velocityField,m_LargestRegion);
405  tmpMatrix.fill(0);
406  VelocityFieldIndexType curIndex;
407  VelocityFieldPointType curPoint;
408  VelocityFieldPixelType curDisp;
409 
410  affineIterator = itk::ImageRegionIterator < AffineFieldType > (affineField,m_LargestRegion);
411  while (!svfIterator.IsAtEnd())
412  {
413  curLog = affineIterator.Get();
414 
415  unsigned int pos = 0;
416  for (unsigned int j = 0;j < NDimensions;++j)
417  for (unsigned int k = 0;k <= NDimensions;++k)
418  {
419  tmpMatrix(j,k) = curLog[pos];
420  ++pos;
421  }
422 
423  curIndex = svfIterator.GetIndex();
424  velocityField->TransformIndexToPhysicalPoint(curIndex,curPoint);
425  for (unsigned int i = 0;i < NDimensions;++i)
426  {
427  curDisp[i] = tmpMatrix(i,NDimensions);
428  for (unsigned int j = 0;j < NDimensions;++j)
429  curDisp[i] += tmpMatrix(i,j) * curPoint[j];
430  }
431 
432  svfIterator.Set(curDisp);
433 
434  ++affineIterator;
435  ++svfIterator;
436  }
437 
438  // Create the final transform
439  typename BaseOutputTransformType::Pointer resultTransform = BaseOutputTransformType::New();
440  resultTransform->SetIdentity();
441  resultTransform->SetParametersAsVectorField(velocityField.GetPointer());
442 
443  this->SetOutput(resultTransform);
444 }
445 
446 } // end of namespace anima
BaseMatrixTransformType::ParametersType ParametersType
BaseInputTransformType * GetInputTransform(unsigned int i)
std::vector< BaseInputTransformPointer > & GetInputTransforms()
std::vector< RegionType > & GetInputRegions()
itk::MatrixOffsetTransformBase< InternalScalarType, NDimensions, NDimensions > BaseMatrixTransformType
std::vector< InternalScalarType > & GetInputWeights()
VelocityFieldType::PointType VelocityFieldPointType
void SetInput(InputType &input)
PointType & GetInputOrigin(unsigned int i)
VelocityFieldType::PixelType VelocityFieldPixelType
VelocityFieldType::IndexType VelocityFieldIndexType
void SetOutput(BaseOutputTransformType *output)
Class to compute many log-vectors in a multi-threaded way.
InternalScalarType GetInputWeight(unsigned int i)