ANIMA  4.0
animaMEstimateSVFImageFilter.hxx
Go to the documentation of this file.
1 #pragma once
3 
4 #include <itkImageRegionIteratorWithIndex.h>
5 #include <itkImageRegionConstIteratorWithIndex.h>
6 
8 
9 namespace anima
10 {
11 
12 template <class TScalarType, unsigned int NDegreesOfFreedom, unsigned int NDimensions>
13 void
16 {
17  unsigned int nbInputs = this->GetNumberOfIndexedInputs();
18  if (nbInputs != 1)
19  itkExceptionMacro("Error: There should be one input...");
20 
21  WeightImagePointer tmpWeights = WeightImageType::New();
22  typedef itk::ImageRegionIterator <WeightImageType> WeightIteratorType;
23 
24  WeightIteratorType weightOriginalIterator(m_WeightImage,this->GetInput()->GetLargestPossibleRegion());
25 
26  tmpWeights->SetRegions (this->GetInput()->GetLargestPossibleRegion());
27  tmpWeights->SetSpacing (this->GetInput()->GetSpacing());
28  tmpWeights->SetOrigin (this->GetInput()->GetOrigin());
29  tmpWeights->SetDirection (this->GetInput()->GetDirection());
30  tmpWeights->Allocate();
31  tmpWeights->FillBuffer(0);
32 
33  WeightIteratorType tmpWeightIterator(tmpWeights,tmpWeights->GetLargestPossibleRegion());
34 
35  while (!tmpWeightIterator.IsAtEnd())
36  {
37  if (weightOriginalIterator.Value() <= 0)
38  {
39  ++weightOriginalIterator;
40  ++tmpWeightIterator;
41  continue;
42  }
43 
44  tmpWeightIterator.Set(1.0);
45  ++weightOriginalIterator;
46  ++tmpWeightIterator;
47  }
48 
50  typename WeightSmootherType::Pointer weightSmooth = WeightSmootherType::New();
51 
52  weightSmooth->SetInput(tmpWeights);
53  weightSmooth->SetSigma(m_FluidSigma);
54  weightSmooth->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());
55 
56  weightSmooth->Update();
57 
59  typename FieldSmootherType::Pointer fieldSmooth = FieldSmootherType::New();
60 
61  fieldSmooth->SetInput(this->GetInput());
62  fieldSmooth->SetSigma(m_FluidSigma);
63  fieldSmooth->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());
64 
65  fieldSmooth->Update();
66 
67  InputImagePointer smoothSVFImage = fieldSmooth->GetOutput();
68  smoothSVFImage->DisconnectPipeline();
69 
70  WeightImagePointer smoothWeightImage = weightSmooth->GetOutput();
71 
72  OutputPixelType curDisp;
73  OutputPixelType originDisp;
74  double averageDist = 0;
75  unsigned int numPairings = 0;
76  InputIndexType tmpIndex;
77 
78  typedef itk::ImageRegionIterator <WeightImageType> WeightIteratorWithIndexType;
79  WeightIteratorWithIndexType tmpWeightIteratorWithIndex(tmpWeights,tmpWeights->GetLargestPossibleRegion());
80 
81  while (!tmpWeightIteratorWithIndex.IsAtEnd())
82  {
83  if (tmpWeightIteratorWithIndex.Value() <= 0)
84  {
85  ++tmpWeightIteratorWithIndex;
86  continue;
87  }
88 
89  tmpIndex = tmpWeightIteratorWithIndex.GetIndex();
90  curDisp = smoothSVFImage->GetPixel(tmpIndex);
91  curDisp /= smoothWeightImage->GetPixel(tmpIndex);
92 
93  originDisp = this->GetInput()->GetPixel(tmpIndex);
94 
95  double dist = 0;
96  for (unsigned int i = 0;i < NDegreesOfFreedom;++i)
97  dist += (curDisp[i] - originDisp[i]) * (curDisp[i] - originDisp[i]);
98 
99  averageDist += dist;
100 
101  ++numPairings;
102  ++tmpWeightIteratorWithIndex;
103  }
104 
105  m_AverageResidualValue = averageDist / numPairings;
106 
107  // Now compute image of spatial weights
108  OutputImageRegionType tmpRegion;
109  InputIndexType centerIndex, curIndex;
110  InputPointType curPosition, centerPosition;
111  m_NeighborhoodHalfSizes.resize(NDimensions);
112 
113  for (unsigned int i = 0;i < NDimensions;++i)
114  {
115  tmpRegion.SetIndex(i,0);
116  m_NeighborhoodHalfSizes[i] = std::ceil(3.0 * m_FluidSigma / this->GetInput()->GetSpacing()[i]);
117  tmpRegion.SetSize(i,2 * m_NeighborhoodHalfSizes[i] + 1);
118  centerIndex[i] = m_NeighborhoodHalfSizes[i];
119  }
120 
121  typename WeightImageType::Pointer internalSpatialWeight = WeightImageType::New();
122 
123  internalSpatialWeight->Initialize();
124  internalSpatialWeight->SetRegions (tmpRegion);
125  internalSpatialWeight->SetSpacing (this->GetInput()->GetSpacing());
126  internalSpatialWeight->SetOrigin (this->GetInput()->GetOrigin());
127  internalSpatialWeight->SetDirection (this->GetInput()->GetDirection());
128  internalSpatialWeight->Allocate();
129 
130  WeightIteratorWithIndexType spatialWeightItr(internalSpatialWeight,tmpRegion);
131  internalSpatialWeight->TransformIndexToPhysicalPoint(centerIndex,centerPosition);
132 
133  m_InternalSpatialKernelWeights.clear();
134  m_InternalSpatialKernelIndexes.clear();
135 
136  while (!spatialWeightItr.IsAtEnd())
137  {
138  curIndex = spatialWeightItr.GetIndex();
139  internalSpatialWeight->TransformIndexToPhysicalPoint(curIndex,curPosition);
140 
141  double centerDist = 0;
142  for (unsigned int i = 0;i < NDimensions;++i)
143  centerDist += (centerPosition[i] - curPosition[i]) * (centerPosition[i] - curPosition[i]);
144 
145  if (centerDist > 9.0 * m_FluidSigma * m_FluidSigma)
146  {
147  ++spatialWeightItr;
148  continue;
149  }
150 
151  centerDist = std::sqrt(centerDist) / (3.0 * m_FluidSigma);
152  // Wendland function phi_{3,1}
153  double wendlandFunctionValue = std::pow((1.0 - centerDist), 4) * (4.0 * centerDist + 1.0);
154 
155  if (wendlandFunctionValue > 0.05)
156  {
157  m_InternalSpatialKernelWeights.push_back(wendlandFunctionValue);
158  m_InternalSpatialKernelIndexes.push_back(curIndex);
159  }
160 
161  ++spatialWeightItr;
162  }
163 }
164 
165 template <class TScalarType, unsigned int NDegreesOfFreedom, unsigned int NDimensions>
166 void
169 {
170  typedef itk::ImageRegionIteratorWithIndex <TOutputImage> OutRegionIteratorType;
171  OutRegionIteratorType outIterator(this->GetOutput(), outputRegionForThread);
172 
173  unsigned int numMaxEltsRegion = m_InternalSpatialKernelIndexes.size();
174 
175  std::vector <double> weightsVector(numMaxEltsRegion);
176  std::vector <double> deltaVector(numMaxEltsRegion);
177  std::vector <InputPixelType> logTrsfsVector(numMaxEltsRegion);
178 
179  InputIndexType centerIndex;
180 
181  OutputImageRegionType largestRegion = this->GetOutput()->GetLargestPossibleRegion();
182  std::vector <unsigned int> largestBound(NDimensions,0);
183  for (unsigned int i = 0;i < NDimensions;++i)
184  largestBound[i] = largestRegion.GetIndex()[i] + largestRegion.GetSize()[i] - 1;
185 
186  InputIndexType inputIndex;
187  OutputPixelType outValue, outValueOld;
188  unsigned int numKernelWeights = m_InternalSpatialKernelWeights.size();
189 
190  while (!outIterator.IsAtEnd())
191  {
192  outValue.Fill(0);
193  centerIndex = outIterator.GetIndex();
194 
195  double sumAbsoluteWeights = 0;
196  unsigned int pos = 0;
197 
198  for (unsigned int i = 0;i < numKernelWeights;++i)
199  {
200  bool indexOk = true;
201  for (unsigned int j = 0;j < NDimensions;++j)
202  {
203  int testIndex = m_InternalSpatialKernelIndexes[i][j] + centerIndex[j] - m_NeighborhoodHalfSizes[j];
204  if ((testIndex < 0)||(testIndex > largestBound[j]))
205  {
206  indexOk = false;
207  break;
208  }
209 
210  inputIndex[j] = testIndex;
211  }
212 
213  double weight = 0.0;
214 
215  if (indexOk)
216  weight = m_WeightImage->GetPixel(inputIndex);
217 
218  if (weight > 0.0)
219  {
220  logTrsfsVector[pos] = this->GetInput()->GetPixel(inputIndex);
221  weightsVector[pos] = weight;
222  sumAbsoluteWeights += weightsVector[pos];
223 
224  weightsVector[pos] *= m_InternalSpatialKernelWeights[i];
225  ++pos;
226  }
227  }
228 
229  unsigned int numEltsRegion = pos;
230 
231  if ((sumAbsoluteWeights <= 0)||(numEltsRegion < 1))
232  {
233  outIterator.Set(outValue);
234  ++outIterator;
235  continue;
236  }
237 
238  bool stopLoop = false;
239  unsigned int numIter = 0;
240  std::fill(deltaVector.begin(),deltaVector.begin()+numEltsRegion,1.0);
241 
242  while (!stopLoop)
243  {
244  ++numIter;
245 
246  outValueOld = outValue;
247  outValue.Fill(0);
248 
249  double sumWeights = 0;
250  for (unsigned int i = 0;i < numEltsRegion;++i)
251  {
252  double tmpWeight = weightsVector[i] * deltaVector[i];
253  outValue += logTrsfsVector[i] * tmpWeight;
254 
255  sumWeights += tmpWeight;
256  }
257 
258  outValue /= sumWeights;
259 
260  if (numIter == m_MaxNumIterations)
261  stopLoop = true;
262 
263  if (!stopLoop)
264  stopLoop = checkConvergenceThreshold(outValueOld,outValue);
265 
266  if (!stopLoop)
267  {
268  for (unsigned int i = 0;i < numEltsRegion;++i)
269  {
270  double residual = 0;
271  for (unsigned int j = 0;j < NDegreesOfFreedom;++j)
272  residual += (outValue[j] - logTrsfsVector[i][j]) * (outValue[j] - logTrsfsVector[i][j]);
273 
274  deltaVector[i] = std::exp(- residual / (m_AverageResidualValue * m_MEstimateFactor));
275  }
276  }
277  }
278 
279  outIterator.Set(outValue);
280  ++outIterator;
281  }
282 }
283 
284 template <class TScalarType, unsigned int NDegreesOfFreedom, unsigned int NDimensions>
285 bool
288 {
289  for (unsigned int i = 0;i < NDegreesOfFreedom;++i)
290  {
291  if (std::abs(outVal[i] - outValOld[i]) > m_ConvergenceThreshold)
292  return false;
293  }
294 
295  return true;
296 }
297 
298 } // end of namespace anima
Superclass::OutputImageRegionType OutputImageRegionType
void DynamicThreadedGenerateData(const OutputImageRegionType &outputRegionForThread) ITK_OVERRIDE